Skip to content

Instantly share code, notes, and snippets.

@aliyome
Last active May 15, 2024 06:15
Show Gist options
  • Save aliyome/3b8a45e40569f35b6fa6 to your computer and use it in GitHub Desktop.
Save aliyome/3b8a45e40569f35b6fa6 to your computer and use it in GitHub Desktop.
レガシーVBはもういやだ

Modern Visual Basic

2014.5.10


はじめに

今日話す内容は

言語機能

についてです。

IDEとしての機能や、.NET Frameworkの各名前空間については殆ど触れません


Agenda

  • VisualStudio(VS)と.NETってそもそも何なのか
  • VS2003からVS2013までの変更点を時系列順に列挙
  • VS2003とVS2013の違いを列挙(↑のまとめ)
  • VS2003とVS2013の違いを1項目ずつ解説
  • (おまけ)個人的に使いたいOSS
  • VS2013の機能をふんだんに使った教材用コードを書きました

VSと.NETとはそもそも何なのか

  • VisualStudio
    • 製品としてパッケージ化されたIDE
  • .NET Framework
    • マイクロソフトが開発したアプリケーションの開発・実行環境
  • .NET Framework CLR
    • .NET Frameworkの実行ランタイム
  • C#/VB
    • 主に.NET Frameworkを利用するプログラミング言語

--

versions

図 VSと.NETのバージョン(引用元:++C++; // 未確認飛行C)

--

VSと.NETとC#/VBはそれぞれが密接に関係しあっていますが, 以降の説明では混ぜこぜでお話します. 厳密に知りたい方は随時質問するか,後でググってください.


VS2003 To VS2005

--

VS2003 To VS2005

  • .NET Framework 2.0
  • Generics
  • Using
  • プロパティのSet/Get個別アクセスタイプ
  • Partial Type
  • 非同期実装パターン(EAP)

--

VS2003 To VS2005

  • 匿名メソッド
    • (VS2010)ラムダ式追加
  • イテレータ(C#のみ)
    • (VS2012)VBにもポート
  • Nullable型(C#のみ)
    • (VS2008)VBにもポート

VS2005 To VS2008

--

VS2005 To VS2008

  • .NET Framework 3.0
  • LINQ
  • ローカル型推論
  • 拡張メソッド
  • 匿名型

--

VS2005 To VS2008

  • Nullable型
  • If式
  • Partial Method
  • WPF
  • WCF
  • ASP.NET MVC1

--

VS2005 To VS2008

  • オブジェクト初期化子
  • ラムダ式(C#のみ)
    • (VS2010)VBにもポート
  • コレクション初期化子(C#のみ)
    • (VS2010)VBにもポート
  • 自動実装プロパティ(C#のみ)
    • (VS2010)VBにもポート

VS2008 To VS2010

--

VS2008 To VS2010

  • .NET Framework 4.0
  • TDL
    • 非同期実装パターン(TAP)
    • Rx(ReactiveExtensions)
  • 動的言語ランタイム
  • ラムダ式
  • 自動実装プロパティ
  • コレクション初期化子

--

VS2008 To VS2010

  • 暗黙の行連結
  • 呼び出し階層の表示(C#のみ)
    • (VS2012)VBにもポート
  • ASP.NET MVC2

VS2010 To VS2012

--

VS2010 To VS2012

  • .NET Framework 4.5
  • Async-Await
  • イテレータ
  • 呼び出し階層の表示
  • 呼び出し元情報引数

--

VS2010 To VS2012

  • ByVal不要
  • NuGet
  • ASP.NET MVC3
    • Razor
  • ASP.NET WebAPI
  • SignalR

VS2012 To VS2013

--

VS2012 To VS2013

  • .NET Framework 4.5.1
  • 言語的に大きな変更は無い
  • ASP.NET
  • ASP.NET MVC4
  • (One ASP.NET)

--

One ASP.NET Platform

図 One ASP.NET BUILD2012


まとめましょう


VS2003 To VS2013

追加された機能(個人的な重要度順)

* ローカル型推論
	+ ByVal不要
* Generics
* Using
* LINQ
	+ 匿名メソッド
	+ ラムダ式
	+ 匿名型
	+ オブジェクト初期化子
	+ コレクション初期化子
* 拡張メソッド
* 自動実装プロパティ
* 暗黙の行連結
* 非同期実装パターン(TAP)
* Async-Await
* WPF
* Rx(ReactiveExtensions)
* イテレータ
* If式
* Partial Type
* Nullable型
* Partial Method
* 動的言語ランタイム
* 呼び出し階層の表示
* 呼び出し元情報引数
* ASP.NET MVC5
* ASP.NET WebAPI
* ASP.NET SignalR

使われなくなった機能

* 非ジェネリックコレクション
	+ ジェネリックコレクションを使う
* 非同期実装パターン(APM・EPM)
	+ TAP(Async-Await)を使う
* Threadクラス
	+ Taskを使う

ローカル型推論

Dim num As Integer = 10
  • As Integer 書くのが面倒.
  • でも遅延バインディングを有効にしてしまうと,型に起因するエラーがランタイムにしかわからない,ボクシングが発生して遅い.

--

VB.NET 2003

Dim num = 10  ' TypeOf num Is Object
Dim str = SubString(num, 10)  ' ランタイムエラー(ビルドはできる)

VB.NET 2008

Dim num = 10  ' TypeOf num Is Integer
Dim SubString(num, 10) ' ビルドエラー(ビルド前にもIntellisenseが教えてくれる)

--

ここでも効いてくる型推論

  • 以下のコードは遅延バインディングではありません
For Each v In Values
	Debug.WriteLine(v)
Next
  • 当然 v. ←この時点でインテリセンスが効きます

ByVal不要

  • デフォルトで引数ByValで渡されるのでわざわざ書かなくていい.地味にありがたい
  • 後に出てくる匿名関数・ラムダ式がとっても便利に使える
  • .

ByRefは書いてね


Generic Programming

  • C++のテンプレート/Javaのジェネリック
  • ジェネリックについての説明は必要ないと思うので省いていい?
  • 例えばどういう時に使う?
    • Integer型のみのコレクションが欲しい
    • String型のみのコレクションも欲しい
    • オレオレクラスのコレクションが欲しい
    • どんな型でも引数に取れるメソッドが欲しい

--

VB.NET 2003

Class IntArray
	Private array As New ArrayList

	Public Sub Add(ByVal data As Integer)
		array.Add(data)
	End Sub
End Class

Class StringArray
	Private array As New ArrayList

	Public Sub Add(ByVal data As String)
		array.Add(data)
	End Sub
End Class

クラス間の差は型だけしかない⇒DRYじゃない.

--

VB.NET 2005

' クラスを一つ作るだけでいい

Class TypeArray(Of T)
	Private array As New ArrayList

	Public Sub Add(ByVal data As T)
		array.Add(data)
	End Sub
End Class
' 使い方

Sub Method()
	Dim intArray As New TypeArray(Of Integer)
	Dim strArray As New TypeArray(Of String)

	intArray.Add(10) ' OK
	intArray.Add("10") ' BuildError
End Sub

--

実は.NET Frameworkも2.0からジェネリック対応になっているので,型指定コレクションは標準で用意されています.

Sub Method()
	'コレだけで超多機能な型指定コレクションが使えます
	Dim intList As New List(Of Integer)
	intList.Add(10)
	intList.Count()
	intList.Sort()
End Sub

--

余談

VB.NET 2003 で List(Of String)と同等のコレクションクラス (String型のみを格納する標準的な機能(Count, IndexOf, Insert, Remove等)を持つコレクションクラス) を作るには?

' IListを継承する
Class MyCollection
	Implements IList

--

Class MyCollection
	Implements IList

	Public Sub CopyTo(ByVal array As System.Array, ByVal index As Integer) Implements System.Collections.ICollection.CopyTo

	End Sub

	Public ReadOnly Property Count() As Integer Implements System.Collections.ICollection.Count
		Get

		End Get
	End Property

	Public ReadOnly Property IsSynchronized() As Boolean Implements System.Collections.ICollection.IsSynchronized
		Get

		End Get
	End Property

	Public ReadOnly Property SyncRoot() As Object Implements System.Collections.ICollection.SyncRoot
		Get

		End Get
	End Property

	Public Function GetEnumerator() As System.Collections.IEnumerator Implements System.Collections.IEnumerable.GetEnumerator

	End Function

	Public Function Add(ByVal value As Object) As Integer Implements System.Collections.IList.Add

	End Function

	Public Sub Clear() Implements System.Collections.IList.Clear

	End Sub

	Public Function Contains(ByVal value As Object) As Boolean Implements System.Collections.IList.Contains

	End Function

	Public Function IndexOf(ByVal value As Object) As Integer Implements System.Collections.IList.IndexOf

	End Function

	Public Sub Insert(ByVal index As Integer, ByVal value As Object) Implements System.Collections.IList.Insert

	End Sub

	Public ReadOnly Property IsFixedSize() As Boolean Implements System.Collections.IList.IsFixedSize
		Get

		End Get
	End Property

	Public ReadOnly Property IsReadOnly() As Boolean Implements System.Collections.IList.IsReadOnly
		Get

		End Get
	End Property

	Default Public Property Item(ByVal index As Integer) As Object Implements System.Collections.IList.Item
		Get

		End Get
		Set(ByVal Value As Object)

		End Set
	End Property

	Public Sub Remove(ByVal value As Object) Implements System.Collections.IList.Remove

	End Sub

	Public Sub RemoveAt(ByVal index As Integer) Implements System.Collections.IList.RemoveAt

	End Sub
End Class

'とっても面倒くさい

--

  • IListを実装せずにオレオレコレクションクラスで良いのでは?
    • みんな大好きForEach文が使えない
    • Sortができない
    • Filterができない
    • ⇒使いづらい⇒使われない

--

余談2

  • For Eachが使える場面でまさかForなんて使ってませんよね?

  • For Each文を使うには?

  • ⇒IEnumerableを実装すれば使えます(VS2005のVBではクッソ面倒くさいけど)

  • ※ VisualStudio2012のVBからは,イテレータ(Yield)を使うことでIEnumerableの実装がクッソ簡単になっています.上記は忘れてください.数行で書けるようになります.

Class MyCollection
	Implements IEnumerable

	Private _array As New ArrayList

	Public Sub Add(ByVal o As Object)
		_array.Add(o)
	End Sub

	Public Function GetEnumerator() As System.Collections.IEnumerator Implements System.Collections.IEnumerable.GetEnumerator
		Return New MyCollectionEnumerator(_array)
	End Function

	Private Class MyCollectionEnumerator
		Implements IEnumerator

		Private _index As Integer = -1
		Private ReadOnly _array As ArrayList

		Public Sub New(ByVal array As ArrayList)
			_array = array
		End Sub
		Public ReadOnly Property Current() As Object Implements System.Collections.IEnumerator.Current
			Get
				Return _array(_index)
			End Get
		End Property

		Public Function MoveNext() As Boolean Implements System.Collections.IEnumerator.MoveNext
			_index += 1
			Return _index <> _array.Count
		End Function

		Public Sub Reset() Implements System.Collections.IEnumerator.Reset
			_index = -1
		End Sub
	End Class
End Class

Using文(リソース管理)

IDbDataReader(OracleDataReaderとかの抽象クラス)を使い終わったらDispose()を必ず呼びたい

--

VB.NET 2003

Dim rdr As OracleDataReader

Try
	dllxv.XVFOPNRDR(rdr, sql)
	' do something
Finally
	rdr.Dispose()
End Try
  • 忘れがち.
  • リソースリークは気づきにくい(でも少しずつ被害が・・・)
  • Try~Finallyは例外を記述するための構文なのにリソース管理に用いるのは普通じゃない(けど慣例化している)

 

VB.NET 2005

Using rdr
	' do something
End Using 'ここでrdr.Dispose()が例外の有無に関係なく必ず呼ばれる

LINQ

…の前に,以下の5つの説明を先にします.

  • 匿名メソッド
  • ラムダ式
  • オブジェクト初期化子
  • 匿名型
  • コレクション初期化子

匿名関数

  • 使い捨ての関数
  • 関数オブジェクトをメソッド内で直ぐに作れる.
  • いろんな場面で重宝するが,若干コードが読みづらくなる.C#のラムダ式が欲しくなる.(VS2010でVBでも使えるようになった!)
  • VB.NET 2008のLINQでよく使う.ただし,VB.NET 2010以降はラムダ式の方を主に使うので使用頻度は低い.

--

VB.NET 2003

Delegate Sub Action()
Sub WriteHoge()
	Debug.WriteLine("Hoge")
End Sub

Sub Main()
	Dim act As New Action(AddressOf WriteHoge)
	act()
End Sub

VB.NET 2008

Sub Main()
	Dim act = _
		Sub()
			Debug.WriteLine("Hoge")
		End Sub

	act()
End Sub

ラムダ式(VB.NET 2010)

匿名関数のシンタックスシュガー

'ラムダ式
Dim plus = Function(x) x + 1

'匿名関数
Dim plus = Function(x)
			Return x + 1
		 End Function

※余談 C#のラムダ式

var plus = x => x + 1

オブジェクト初期化子

構造体やクラスのアクセス可能フィールド/プロパティの初期化がとっても楽になる.

Structure A
	Public x As Integer
	Public y As Integer
End Structure

VB.NET 2003

Dim a As A
a.x = 10
a.y = 20

VB.NET 2008

Dim a As New A With {.x = 10, .y = 20}

--

どういう場面で使う?

  • 最も有効な場面
  • →インスタンスを宣言せずに,生成してすぐ使う
Dim patients = GetPatients(New SearchOption With {
					.TestPatient = True,
					.Gender = Male,
					.Nyuuin = True
				})

SearchOptionインスタンスが宣言されないのでグローバルスコープが汚れない


匿名型

事前にクラスを定義せずに,オブジェクト初期化子が使える

Dim a As New With {.X = 10, .Y = 20}
Console.WriteLine(a.X) 'a. の時点でインテリセンスが働く
  • 例えば,メソッドの戻り値や引数で,いくつかの変数をまとめて渡したい時に使う.
  • 後述のLINQで多用する.
  • 遅延バインディングでは無い
HogeMethod(strPatno, New {.Name="白十字花子", .Birthday="19500101" } )

コレクション初期化子

配列以外のコレクションもワンライナーで初期化できる

VB.NET 2003

Dim nums As New ArrayList
nums.Add(1)
nums.Add(2)
nums.Add(3)

VB.NET 2008

Dim nums As New List(Of Integer) From {1, 2, 3}

LINQ


LINQ

  • Language INtegrated Query
  • VisualStudio 2008 の最大の変更点.(LINQ前,LINQ後と呼ばれることもあるらしい)

--

'準備---------------------
Class Hoge
	Public Id As Integer
	Public Name As String
End Class

Dim hogeCollection As New ArrayList

hogeCollection.Add(New Hoge(0, "花子"))
hogeCollection.Add(New Hoge(1, "太郎"))
hogeCollection.Add(New Hoge(2, "次郎"))

'クエリ構文-------------------
Dim q =	From h In hogeCollection
		Where h.name.Contains("郎")
		Select h.name

For Each e In q
	Debug.WriteLine(e)
End For

' デバッグ出力------
' 太郎
' 次郎

'メソッド構文(VB.NET 2010)---------
Dim q2 = hogeCollection
		.Where( Function (x) x.name.Contains("郎") )
		.Select(Function (x) x.name )

For Each e In q2
	Debug.WriteLine(e)
End For

' 太郎
' 次郎

' ラムダ式・匿名関数を使わない場合のメソッド構文
q = hogeCollection
	.Where(dlgtContains("郎"))
	.Select(dlgtGetName)

--

LINQ + ラムダ式 = すごい便利!

Dim linq = hoge.
			Where(Function(x) x.kbn = 10).
			Where(Function(x) x.ymd <= 20130828).
			Select(Function(x) x.name.Trim)
  • DataViewと違って,インテリセンスが完全に効く
  • DataViewよりパフォーマンスがいい(Boxingが発生しない,式の評価が遅延される)
  • DataViewよりも多機能(Count, Sum, Aggregate, SelectMany, Join, Uniqueなど)

--

LINQってどこで使うの?

  • IEnumerable(Of T)を実装する全てのコレクション処理で使える.使うべき.
  • 例えば,VB.NET 2003 で良くある処理
dtv.RowFilter = "ORD_INF_KBN = '20' "
For Each row As DataRowView In dtv
	Debug.WriteLine(CStr(row("PATNO")))
Next

このコードの潜在的な危険性

  • dtvに ORD_INF_KBN 列は存在するか?
  • ORD_INF_KBN 列は String型 なのか?
  • dtvに PATNO 列は存在するか?
  • CStr(row("PATNO"))で正しくキャストできるか?

たった4行で4つもランタイムにしかわからないバグの可能性が潜んでいるし,コードを書く際,dtvに何の列が存在するのか覚えていないとコードが書けない,読めない

--

LINQを使うと?

linq.Where(Function(x) x.Kbn = '20')
	.WriteLine(Function(x) x.Patno )

Class Hoge
	Public Kbn As String
	Public Patno As String
End Class

--

DataViewの問題が(一応)全て解決している.

  • dtvに ORD_INF_KBN 列は存在するか?
    • 存在するプロパティ(Public Kbn As String)以外を指定するとビルドエラー
    • インテリセンスが利くのでコード書く時点で候補が提示される
  • ORD_INF_KBN 列は String型 なのか?
    • KbnプロパティはString型.考える必要なし
  • dtvに PATNO 列は存在するか?
    • 存在するプロパティのみ指定可能.考える必要なし
  • CStr(row("PATNO"))で正しくキャストできるか?
    • PatnoプロパティはString型なのでキャスト不要.
    • 型からはわからない情報(Nothingかどうか)等は従来通り考慮する必要あり

--

実際にコード見たほうが早い


拡張メソッド (VB.NET 2008)

  • クラスのメソッドを,クラスの外に書ける.
  • というより,第1引数の型のメソッドを書ける
  • 既存のコードを変更することができないクラス・インターフェイスを拡張できる
    • 例えば,DataTable.ToCsv()とか作ればデバッグが楽になる
    • C1FlexGrid.ToString()を作ってデバッグ出力してみたりとか
Dim tbl As DataTable

' tbl.ToCsv() というメソッド呼び出しをしたい!

<Extension()>
Public Function ToCsv(t As DataTable) As String
	' ここでCSV出力する
End Function

tbl.ToCsv() ' ビルドOK

自動実装プロパティ

  • Set/Getを持つプロパティをワンライナーで記述できる.
  • パブリックフィールドは全てプロパティにすべき
    • シグニチャを変えずに後から実装を変更できる

--

VB.NET 2003

Class C
	Private _str As String
	Public Property Str() As String
		Get
			Return _str
		End Get
		Set(ByVal Value)
			_str = Value
		End Set
	End Property
End Class

VB.NET 2010

Class C
	Public Property Str As String
End Class

--

でも実際良く使うのはこんなやつですよね…(自動実装プロパティ使えない)

Class C
	Private _str As String
	Public Property Str() As String
		Get
			Return _str
		End Get
		Private Set(ByVal Value)
			_str = Value
		End Set
	End Property

	' または
	Public ReadOnly Property Str2() As String
		Get
			Return _str
		End Get
	End Property
End Class

暗黙の行連結

引数リストが長いとき,複数行に分けて書きたい

Public Sub Hoge(ByVal a As Integer, ByVal b As Integer, ByVal c As Integer)

' VB.NET 2003
Public Sub Hoge(ByVal a As Integer, _
					 ByVal b As Integer, _
					 ByVal c As Integer)
' VB.NET 2010
Public Sub Hoge(ByVal a As Integer,
					 ByVal b As Integer,
					 ByVal c As Integer)
  • ほかにも,いろんな場所で暗黙の行連結が有効になっているので,今まで "_" を書いていた部分が省略できるかも

非同期処理

  • .NET Framework4.0からTaskクラスが追加され,TAP(Task-based Asynchronous Pattern)が主流に.
  • 現在の非同期処理もTAPが主流です.APM,EAPは駆逐されました.完全に忘れていいです.
Task.Factory.StartNew(New Addressof SetButtonEnableFalse)
			.ContinueWith(New Addressof Sleep30Sec)
			.ContinueWith(New Addressof SetButtonEnableTrue,
						TaskScheduler.FromCurrentSynchronizationContext())

--

余談

--

AEP(Asynchronous Programming Model)

Dim asyncHoge = New dlgtAsync(AddressOf subAsyncHoge)
Dim req = WebRequest.Create("http://hoge")
req.BeginGetResponse(asyncHoge, req)

Delegate Function dlgtAsync(ByVal ar As IAsyncResult)
Sub subAsyncHoge(ByVal ar As AsyncResult)
	Dim res = (ar.AsyncState).EndGetResponse(ar)
End Sub

--

EAP(Event-based Asynchronous Pattern)

Dim c As New WebClient
c.Encoding = Encoding.UTF8

AddHandler c.DownloadStringCompleted, AddressOf subWriteString

c.DownloadStringAsync(New Uri("http://hoge"))

Sub subWriteString(ByVal sender As Object, ByVal args As DownloadStringCompletedEventArgs)
	Dim result = args.Result
	Console.WriteLine(result)
End Sub

Async-Await (VB.NET 2012)

  • LINQと同じ位の衝撃
  • 非同期プログラムが革新的に簡単に書ける(同期的にかける).
    • Reactive Extensionsと比べても楽
Async Sub btnOK_Click(sender As Object, e As RoutedEventArgs)
	Me.btnOK.IsEnabled = False
	Await Task.Run(New AddressOf DoSomething)
	Me.btnOK.IsEnabled = True
End Sub

WPF

  • Windows.Formsに代わる,UIとロジックを分離して記述できるGUIフレームワーク.
    • MVVMアーキテクチャ
    • XamlでUIを記述する
    • マルチ解像度に対応できる
    • Windows.Formsとは異なるパラダイムで設計されているので習得にはかなーり時間かかりそう
  • Expression Blend という,UIデザインのみを作りこめるツールも標準である

Rx(Reactive Extensions)

  • この頃からLINQを非同期に記述できる,**Rx(Reactive Extensions)**が流行しだした.
  • .NET Frameworkには含まれていないが,Microsoftの正規プロダクト
  • 現在でももちろん使われている素晴らしい技術
  • ただし,今ならTAPのAsync-Awaitである程度代用できる

--

例えばこういうことができます.

'ボタンのClickイベントがRaiseされたら
'ボタンをEnable=Falseにする
'その後別スレッドの監視を開始し
'何かしら時間のかかる作業を行う
'最初のスレッドの監視を再開し
'ボタンを有効にする

Observable
	.FromEventPattern(Me.btnOK, "Click")
	.Do(SetEnableFalse)
	.ObserveOn(Scheduler.ThreadPool)
	.Do(DoSomething)
	.ObserveOn(SynchronizationContext.Current)
	.Subscribe(SetEnableTrue)

イテレータ(Yield)

  • IEnumerable(Of T)の実装が驚くほど簡単になる.
  • つまりForEach対応のコレクションクラスが簡単に作れる.
  • ForEachが使えるということはLINQも使える.
  • C#が2005で導入した機能がようやくVBにポーティングされた.
  • LINQと合わさって最強に見える.
  • コレクションクラス作るのが面倒だからDataTableにデータ突っ込んでDataViewでゴチャゴチャやる.ということが減らせる.
Class HogeCollection
	Implements IEnumerable(Of Hoge)

	Dim _list As New List(Of Hoge)

	Iterator Function GetEnumerator() As IEnumerator(Of Hoge)
		For Each h In _list
			Yield h ' For文でまわしてYield呼ぶだけ!
		Next
	End Function
End Class

--

再掲 Yieldを使わない場合(VB.NET 2003)

Class MyCollection
	Implements IEnumerable

	Private _array As New ArrayList

	Public Sub Add(ByVal o As Object)
		_array.Add(o)
	End Sub

	Public Function GetEnumerator() As System.Collections.IEnumerator Implements System.Collections.IEnumerable.GetEnumerator
		Return New MyCollectionEnumerator(_array)
	End Function

	Private Class MyCollectionEnumerator
		Implements IEnumerator

		Private _index As Integer = -1
		Private ReadOnly _array As ArrayList

		Public Sub New(ByVal array As ArrayList)
			_array = array
		End Sub
		Public ReadOnly Property Current() As Object Implements System.Collections.IEnumerator.Current
			Get
				Return _array(_index)
			End Get
		End Property

		Public Function MoveNext() As Boolean Implements System.Collections.IEnumerator.MoveNext
			_index += 1
			Return _index <> _array.Count
		End Function

		Public Sub Reset() Implements System.Collections.IEnumerator.Reset
			_index = -1
		End Sub
	End Class
End Class

If式

  • 所謂3項演算子.
  • VB.NET2003の不十分な3項演算子(IIfメソッド)を強化したもの
  • 戻り値 = If(条件, 真の場合, 偽の場合)
' VB.NET 2003
hoge = IIf(IsDBNull(hoge), "", CStr(hoge))
' hogeがDBNullかどうかに関わらず真と偽の両方の引数が評価される.
' 例えば上の例では,hogeがDBNullの場合にCStr(hoge)が評価されて落ちる.

' VB.NET 2008
hoge = If(IsDBNull(hoge), "", CStr(hoge))
' hogeがDBNullなら""しか評価されない```


---

## VS2003 To VS2013 簡易まとめ

* ジェネリックの使い方に慣れてください* ラムダ式の使い方に慣れてください* リソース管理はUsingを使ってください* 型推論は強力なので頼ってください* 型推論は**遅延バインディングではありません**
* LINQはとっても便利なので使い方に慣れてください* オブジェクト初期化子コレクション初期化子も便利です* 複数行にまたがるコードでも "_" が不要になる場合が多くあります* 非同期処理はTAP(Async/Await)を真っ先に検討してください---

# おまけ

OSSの紹介

* Dapper
	+ とっても便利なMicroORM
* ReactiveExtensions
	+ 非同期LINQ

---

以上---

### 言語機能の学習には以下のサイトが非常に有効です* C#によるプログラミング入門 | ++C++;// 未確認飛行 C
	+ http://ufcpp.net/study/csharp/
* .NET Framework | ++C++;// 未確認飛行 C
	+ http://ufcpp.net/study/dotnet/index.html
---

C#のサイトですが現在C#の機能の8割はVBにポートされているので気にせず読みましょう
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment