C#でのvarキーワードの使用


406

C#3で 'var'キーワードの使用について同僚と話し合った後、varを介した型推論の適切な使用についての人々の意見はどうだったのでしょうか。

たとえば、私は疑わしい状況でvarを怠惰に使用しました。例:-

foreach(var item in someList) { // ... } // Type of 'item' not clear.
var something = someObject.SomeProperty; // Type of 'something' not clear.
var something = someMethod(); // Type of 'something' not clear.

varのより正当な用途は次のとおりです。

var l = new List<string>(); // Obvious what l will be.
var s = new SomeClass(); // Obvious what s will be.

興味深いことに、LINQは少し灰色の領域のようです。例:-

var results = from r in dataContext.SomeTable
              select r; // Not *entirely clear* what results will be here.

IEnumerableを実装する型であることは、結果がどのようになるかは明らかですが、新しいオブジェクトを宣言するvarと同じように完全には明らかではありません。

オブジェクトへのLINQに関しては、さらに悪い例です。

var results = from item in someList
              where item != 3
              select item;

これは、同等のforeach(var item in someList){// ...}同等のものと同じです。

ここで型の安全性について本当の懸念があります。たとえば、IEnumerable <int>とIEnumerable <double>を受け入れるオーバーロードされたメソッドにそのクエリの結果を配置すると、呼び出し元が誤って間違った型を渡す可能性があります。

var 強い型付けを維持しますが、問題は、型が定義上すぐに明らかにならないことが危険であるかどうかです。オーバーロードは、誤った型をメソッドに誤って渡したときにコンパイラエラーが発行されないことを意味する場合に拡大されます。


68
varを使用することは問題ありませんが、「タイプを理解する必要がない」というのは、それを使用する非常に悪い理由のように思われます... タイプは何かを知っているはずです。var は、入力を避けるための単なるショートカットです
Thomas Levesque、

53
var i = 0;==失敗!var c = new CrazyFrigginLongClassName();==勝つ!
dotjoe

6
「VarはVB / VBAバリアントタイプも思い出させます。また、その場所もありました。(何年も前から)その使用方法は望ましいタイプではなく、リソースを大量に消費していたことを思い出します。」<-これは、C#の 'var'タイプがVB / VBAバリアントタイプとは関係がないため、これがおとりの質問であることを示しています。
user7116

20
var readabilityBeDamned = true;
スポールソン2010年

9
ここに記載されているすべての例の問題は、コードの1行に注目していることです。"var"宣言が次々と表示されると、手に負えなくなります。読みやすさは主観的ですが、varはかなり使用されるよりもはるかに乱用されています。
jro

回答:


293

私はまだ考えてvarいくつかのケースでは、コードを読みやすくすることができます。Ordersプロパティを持つCustomerクラスがあり、それを変数に割り当てたい場合は、次のようにします。

var orders = cust.Orders;

Customer.OrdersがIEnumerable<Order>であるObservableCollection<Order>かどうかは関係ありません。または、BindingList<Order>そのリストをメモリに保持して繰り返し処理したり、後でそのカウントや何かを取得したりするだけです。

上記の宣言を以下と比較してください。

ObservableCollection<Order> orders = cust.Orders;

私にとって、型名は単なるノイズです。そして、戻ってCustomer.Ordersのタイプをトラックで変更することを決定した場合(たとえば、ObservableCollection<Order>からIList<Order>)、その宣言も変更する必要があります。最初にvarを使用した場合は、行う必要はありません場所。


48
コードを読んでいるときに、明示的な型を目の前に置くのが好きです。タイプなしの「cust.Orders」がここにあることをどのように知ることができますか?はい、マウスをポイントして見つけることができますが、なぜそうしなければならないのですか?:)
Jon Tackabury、2008年

77
しかし、要点は、一般的には問題ではないということです。cust.Ordersは、列挙可能なもの(foreach overなど)であり、どの型でもかまいません。追加のコードは、意図の読み取りを邪魔するだけです。
Matt Hamilton、

67
しかし、cust.Ordersが「列挙できるもの」である必要があるだけの場合は、IEnumerable <Order>として宣言しないことで、その要件を明示的かつ明確にしますか?varとして宣言すると、その要件を効果的に失うことになります。
GrahamS 2009

5
@jonとIEnumerbalの注文= cust.Orders foreach(var order in orders)はどう違いますか?IEnumerableが言う唯一のことは、それをforeachに入れることができるということですが、あなたは以下の行からそれをすでに知っていました
Rune FS

18
「IEnumerableが言う唯一のことは、あなたがそれをforeachに入れることができるということです」-それはまた、あなたができる唯一のことが列挙することであるという意図を表現します。varを使用すると、具象コレクション型のパブリックメンバーへのアクセスとインテリセンスが提供されます。
Joe、

167

私が使う var幅広くいます。これによりコードの可読性が低下するという批判がありましたが、その主張を支持する議論はありません。

確かに、それは私たちが扱っているタイプが明確でないことを意味するかもしれません。だから何?これは、実際には分離された設計のポイントです。インターフェースを扱う場合、変数の型には特に関心がありませんvar真、さらにこのくらいかかりますが、私は、引数は、ビューの読みやすさの点から、同じままであることを考える:プログラマは、実際に変数の型ではなく、変数が何に興味があるべきではない。これが、マイクロソフトが型推論を「ダックタイピング」とも呼ぶ理由です。

では、変数を使用して宣言するとvarどうなりますか?簡単です。IntelliSenseが教えてくれることは何でも実行します。IDEを無視するC#についての推論は、現実には不十分です。実際には、すべてのC#コードは、IntelliSenseをサポートするIDEでプログラムされています。

var宣言された変数を使用していて、変数の目的がわかりにくい場合は、コードに根本的な問題があります。var原因ではなく、症状が見えるようになるだけです。メッセンジャーを責めないでください。

現在、C#チームは、匿名型を作成するLINQステートメントの結果をキャプチャするためにのみ使用するvar必要があることを明記したコーディングガイドラインをリリースしました(ここでは、var)。まあ、それをねじ込みます。C#チームがこのガイドラインに適切な議論を示さない限り、私はそれを無視します。私の専門家および個人的な意見では、それは純粋な愚か者だからです。(申し訳ありません。問題のガイドラインへのリンクはありません。)

実際、なぜ使用してはいけないのかについては(表面的に)良い説明がいくつかありますvarが、それでも大部分は間違っていると私は信じています。「searchabililty」の例を見てみましょう。著者はvarMyTypeが使用されている場所を検索することを難しくしていると主張しています。正しい。インターフェイスもそうです。実際、クラスが使用されている場所を知りたいのはなぜですか?それがインスタンス化される場所にもっと興味があるかもしれませんが、コンストラクタをどこかで呼び出さなければならないので、これはまだ検索可能です(これが間接的に行われる場合でも、型名をどこかに言及する必要があります)。


14
適切なIDEでは、テキスト検索を使用してクラスの使用法を取得するのではなく、IDEに解析ツリーに基づいてそれを行わせるか、それ以外の場合はオブジェクトのタイプを識別します。静的型付けについて話しているので、これは匿名型以外のすべてを見つけます。
ダストマン

6
ドキュメンテーションやvarの自由な使用をせずに100k行のソースを継承したくありません。特に、varとあまり役に立たない変数名を組み合わせる場合。ポイントを説明するとき(または匿名型を処理するとき)に役立つが、本番用コードではそれが役立つと思いますか?
Shea

7
Arnshea:さて、あなたはすでにそこの本当の問題を指摘しました:役に立たない変数名、そして不足しているドキュメント。何varが混乱の原因になっているのか本当にわかりません。確かに、変数のタイプ/サイズを強調することが重要な場合があります(低レベルのビット操作など)。それは結構です:var排他的に使用されるべきだと主張した人はいません。ルールは簡単です。本当に混乱を招く場合は、使用しないでください。
Konrad Rudolph、

17
私が見たvarに反対するすべての例は、プログラマが無意味な変数名を使用することを想定しています。しかし、たぶんこれがvarが型を明示的に指定するより優れて。これにより、プログラマーは適切な変数名を考え出す必要があります。
ライアンランディ

16
マイクロソフトはまた、型推論を「ダックタイピング」と呼んでいます。—彼らは本当にですか?私はショックを受けるだろう...
アントンティキー

118

Varは、私の意見では、C#ではtm良いことです。そのように型付けされた変数は、引き続き強く型付けされますが、定義されている代入の右側から型を取得します。タイプ情報は右側にあるため、ほとんどの場合、左側にも入力する必要はなく、過度に冗長です。これにより、型の安全性を低下させることなく、読みやすさが大幅に向上すると思います。

私の観点からは、変数とメソッドに適切な命名規則を使用することは、明示的な型情報よりも可読性の観点から重要です。タイプ情報が必要な場合は、いつでも(VSの)変数にカーソルを合わせて取得できます。ただし、一般的には、明示的な型情報は読者には必要ありません。開発者にとって、VSでは、変数の宣言方法に関係なく、Intellisenseを引き続き使用できます。以上をすべて説明した後でも、型を明示的に宣言することが理にかなっている場合はまだあるかもしれません-おそらく、List<T>、それをIEnumerable<T>あなたの方法で。インターフェイスを確実に使用するために、インターフェイスタイプの変数を宣言することで、これを明示的にすることができます。または、おそらく、初期値なしで変数を宣言する必要があります-ある条件に基づいて値をすぐに取得するためです。その場合はタイプが必要です。タイプ情報が有用または必要な場合は、先に進んで使用してください。しかし、私は通常、それは必要ではなく、ほとんどの場合、コードがなくてもコードを読みやすくなると感じています。


3
全体的に同意します。私の意見では、ここで重要な点は、意図が明確であることを確認することです。チームの大多数の開発者にとってそれが明確でない場合、それは有害であり、役に立ちません。とは言っても、私は個人的にはこれの大きなファンですが、私のチームの他の開発者が私の意図を判断するのに苦労したとき、少し自分を抑制しなければなりませんでした。図を行きます。
Steve Brouillard、2010年

3
えっと、タイプが左にある方が読みやすい。ReSharperを使用すると、とにかく右側の型を再入力する必要がないので、邪魔になりません。
BlueRaja-Danny Pflughoeft、

1
@BlueRaja-良い変数名を使用することで、通常、理解のために実際の型を気にする必要がなくなることがわかります。Intellisenseは「var」で定義された変数でも引き続き使用できるため、コーディング時にメソッド/プロパティを選択するためにタイプを知る必要はありません。
tvanfosson

2
それはあなたがコードを読む必要があるときのようにあなたがコーディングしているときのことではありません。
BlueRaja-Danny Pflughoeft

1
それから私は厚い側にいる必要があります、私が読んでいるコードを適切に理解できるようにするには、適切なメソッド名変数名、および操作されている型の理解が必要です。それはより大きな問題の兆候ですが、私はあなたが正しいと思います。信頼の一つ。コードが実行しているように見えることを確実にするには、使用されている型を確認する必要があります。
AnthonyWJones 2010年

91

これらのどちらも絶対に真実ではありません。var読みやすさにプラスとマイナスの両方の影響を与える可能性があります。私の意見でvarは、次のいずれかに該当する場合に使用する必要があります。

  1. 型は匿名です(この場合、varである必要があるため、ここでは選択肢がありません)。
  2. タイプは、割り当てられた式(つまりvar foo = new TypeWithAReallyLongNameTheresNoSenseRepeating())に基づいて明らかです

var構文上の砂糖であるため、パフォーマンスへの影響はありません。コンパイラはタイプを推測し、ILにコンパイルされるとそれを定義します。それについて実際に動的なものは何もありません。


1
私は後者の場合を超える長い制限があるものの、その両方に同意し、タイプがあれば、その場合には、強く型付けされた「TypeWithAReallyLongNameTheresNoSenseRepeatingにはShortType当量は、」より多くの理にかなって、通常、入れ子になったジェネリック引数のたくさんのジェネリック型だということであれば
イオントディレル

12
私は宗教戦争を始めたいとは思っていませんが、個人的にはイオンに反対する傾向があります。私は非常に長く、非常に正確な型名(ala Uncle Bob Martin)を、短縮された、おそらくあいまいな、より短い型名よりもはるかに好みます。名前の長さを人為的に膨らませることにも同意しないという警告を追加します。5つの文字がはっきりと意思を示す簡潔な名前を作成した場合、5及びません25.使用
スティーブBrouillard

2
@Steve:私はあなたに同意する必要があります。「短い型」(名前を短縮する目的でのみ特定のジェネリック型から継承することを想定している)を作成することはお勧めできません。ジェネリック型からコンストラクタを複製して渡す必要があります。また、ジェネリック型から継承する別の型を関数に渡さないようにする必要があります。あなたはtypedefそうでないときに継承を使用しています。
Adam Robinson

7
varタイプが明らかなときに使用しますか?たぶん、しかし、真の利益はタイプが問題ではないときです。あなたがそのようなvar customers = whatever; var query = from c in customers select stuffことをしているなら、「顧客」の正確なタイプが何であるかは重要ではありません。使い方は明らかで、それで十分です。そして、実際のタイプが扱いにくい場合、それを抑制することは価値があります。
Joren、

2
@Kristoffer:私はタグの混乱を解消したいのは理解できますが、それらをクラスにラップすることは(IMO)受け入れられる代替手段ではありません。そのジェネリックタイプの他の(正当な)子クラスの可能性を遮断するためです。有効なパラメータ。using ShortType = LongGenericType<A,B,C>ファイルの先頭でディレクティブを使用します。これにより、同じように読みやすくなり、コンストラクターを再作成する必要がなく、子クラスが候補から除外されません。
アダムロビンソン

68

C#チームのシニアソフトウェアデザインエンジニアであるEric Lippertから:

なぜvarキーワードが導入されたのですか?

2つの理由があります。1つは現在存在していること、もう1つは3.0で出現することです。

最初の理由は、このコードはすべての冗長性のために信じられないほど醜いということです。

Dictionary<string, List<int>> mylists = new Dictionary<string, List<int>>();

そして、それは簡単な例です-私はもっと悪いことを書きました。まったく同じものを2回入力することを強いられるときはいつでも、それは私たちが削除できる冗長性です。書くほうがずっといい

var mylists = new Dictionary<string,List<int>>();

そして、コンパイラーに、割り当てに基づいて型が何であるかを理解させます。

次に、C#3.0では匿名型が導入されています。定義による匿名型には名前がないため、変数の型が匿名の場合、初期化式から変数の型を推測できる必要があります。

鉱山を強調します。記事全体、C#3.0はまだ静的に型付けされており、正直です!、およびその後のシリーズはかなり良いです。

これがvar目的です。他の用途はおそらくそれほどうまくいきません。JScript、VBScript、または動的型付けとの比較は、完全に2段になります。もう一度注意してください。.NETで他の特定の機能を動作させるには、var必要です


リッペルトの議論は奇妙だと思う。誰も2番目のクラス名を入力しません。Intellisenseにそれを記述させますが、彼は振り向いて、コンパイラー/ Intellisenseがそれを処理するため、varの方が優れていると主張します。あなたはそれを両方の方法で持つことはできません!
Dave、

5
C#チームはインテリセンスを制御しません。コンパイラを制御します。いずれにしても、それは主要な問題ではありません。私は、varがタイピングだけを節約することで100ポイントを獲得したとは思いません。
ダストマン

@Dustman:varはタイピングをまったく節約しません。それはあなたにもっと書かせます!
Piotr Perak、

53

varの使用は、賢明に選択された変数名と組み合わせる必要があると思います。

次のようになっていなければ、foreachステートメントでvarを使用しても問題ありません。

foreach (var c in list) { ... }

それがこのようなものだった場合:

foreach (var customer in list) { ... }

...コードを読んでいる人は、「リスト」が何であるかを理解する可能性がはるかに高くなります。リスト変数自体の名前を制御できる場合は、さらに便利です。

同じことが他の状況にも当てはまります。これはかなり役に立ちません:

var x = SaveFoo(foo);

...しかし、これは理にかなっています:

var saveSucceeded = SaveFoo(foo);

それぞれ自分に合っていると思います。私はこれをやっていることに気づきましたが、これは正気ではありません:

var f = (float)3;

12ステップのvarプログラムが必要です。私の名前はマットです。


6
「var f =(float)3;」の唯一の誤りは、「var f = 3f」または「var f = 3.0(単精度が原因)」である必要があります。
MichaelGG 2008年

3
ええええ3fまたは3.0は行く方法です!私たちvar maniacsは一緒に固執する必要があります!
Matt Hamilton、

27
最初の例での実際の問題は、「c」ではなく「list」です。何の「リスト」?「list」の名前は「customers」、「customersWhoOweMoney」、「currentCustomers」、またはもっとわかりやすい名前に変更する必要があります。そして、それが得られたら、「c」は何が含まれるかすでにわかっているので、そのままの状態を保つことができます。
ライアンランディ

4
こんにちはマット!私の名前はケニーと私はvaraddictです。
ケニー

var MattHamil = "Luke Skywalker"; //それを1トン取り除きました
Binoj Antony

40

私たちは、「マシンではなく人のためのコード」という考え方を採用しました。これは、新規開発よりもメンテナンスモードで何倍も長い時間を費やすという前提に基づいています。

私にとって、それはコンパイラが変数のタイプを「知っている」という引数を除外します-確かに、コンパイラはコードのコンパイルを停止するため、最初に無効なコードを書くことはできませんが、次の開発者がコードを読んでいるとき6か月後には、変数が正しくまたは誤って行っていることを推測し、問題の原因をすばやく特定できる必要があります。

したがって、

var something = SomeMethod();

はコーディング標準で非合法ですが、読みやすさを向上させるため、次のことをチームで推奨しています。

var list = new List<KeyValuePair<string, double>>();
FillList( list );
foreach( var item in list ) {
   DoWork( item ); 
}

4
私はそれ(「マシンではなく人のためのコード」)が優れたガイドラインであることを発見しました-これに従うことはより良いコードをもたらし、時期尚早な最適化を回避するのに役立ちます。
タナトス

3
var list = new KeyValuePair <string、double>を取得できませんか?私にとって、リストは物事以上のものを持つことができます。
TTT

「機械ではなく人のためのコード」-アーメン。
user1068352

39

それは悪くはありません、それは主観的である傾向があるより文体的なものです。varを使用する場合と使用しない場合で、矛盾が発生する可能性があります。

もう1つの懸念事項は、次の呼び出しでは、によって返されるタイプをコードを見ただけではわかりませんCallMe

var variable = CallMe();

それがvarに対する私の主な不満です。

メソッドで匿名デリゲートを宣言するときはvarを使用しますが、varを使用する場合よりもvarがきれいに見えますFunc。このコードを考えてみましょう:

var callback = new Func<IntPtr, bool>(delegate(IntPtr hWnd) {
   ...
});

編集:ジュリアンの入力に基づいて最後のコードサンプルを更新しました


3
しかし、本当にその行のタイプを知っている必要がありますか?CallMeが何かを返すことを知っています。というローカル変数variableが作成されたことを知っていれば十分ではないでしょうか?例を拡張しない限り、これはIMOのような非常に堅実な苦情ではありません。
Randolpho

2
それは冗長ではないということではなく、コンパイラーに構文シュガーをさせないことです。これを考慮してください:var getter ...、今、このFunc <object> getter ...、もう1つは、パラメーターとそれが返すものを提供する必要がないことを知っています。あなたは最初から「何をすべきか」を知っており、何かを設計したりリファクタリングしたりするときに、より迅速に決定を下すことができます。手元にすべての情報を持つことは、数人のキャラクターよりも重要です。これは、多くのコードで作業している場合にのみ役立ちます。
Ion Todirel、2010年

2
とにかく、ビジュアルスタジオの話をしているので、変数の上にマウスを1秒間置いて、その型を確認するだけのことは何ですか。とにかく宣言を実行するよりもはるかに良い。
Rubyは

3
一般的な変数と関数名(variableCallMe)は悪い例です。ただし、CallMe()ある種の「電話アプリケーション」の機能である場合は、var call = CallMe(); .... call.HangUp();はるかに理にかなっています。
DankoDurbić

3
@Randolpho:「変数の上にマウスを1秒間置くと、その型が何であるかを確認するだけの大きなメリットは何ですか?」メンテナンスのオーバーヘッドに時間を追加します...プラス1秒は、キーボードからマウスへのコンテキスト切り替えを数えるのではなく、ホバー時間のみです。あなたのことは知りませんが、締め切りはあります。変数にカーソルを合わせてそれがどのタイプかを調べる必要があるたびに、問題の修正に費やしたほうがよい時間です。
Powerlord

36

Varはバリアントとはまったく異なります。変数はまだ強く型付けされています。キーを押さずにそのまま取得するだけです。Visual Studioでこれにカーソルを合わせると、タイプを確認できます。印刷されたコードを読んでいる場合、型を理解するために少し考えなければならない可能性があります。しかし、それを宣言する1行とそれを使用する多くの行があるため、適切な名前を付けることは、コードをわかりやすくするための最良の方法です。

Intellisenseを怠惰に使用していますか?名前全体よりも入力が少なくなります。それとも仕事は少ないが批判に値しないものはありますか?あると思いますが、varはその1つです。


6
+1、とvarは何の関係もないことに注意する人のみVariant
user7116

27

これが必要になる可能性が最も高いのは、匿名型の場合です(100%必要です)。しかし、それはまた、些細な場合の繰り返しを回避し、IMOはその線をより明確にします。単純な初期化のためにタイプを2回表示する必要はありません。

例えば:

Dictionary<string, List<SomeComplexType<int>>> data = new Dictionary<string, List<SomeComplexType<int>>>();

(上記のhscrollを編集しないでください-それはちょっとポイントを証明します!!!)

対:

var data = new Dictionary<string, List<SomeComplexType<int>>>();

ただし、これが誤解を招き、バグを引き起こす可能性がある場合があります。var元の変数と初期化された型が同一でない場合は注意して使用してください。例えば:

static void DoSomething(IFoo foo) {Console.WriteLine("working happily") }
static void DoSomething(Foo foo) {Console.WriteLine("formatting hard disk...");}

// this working code...
IFoo oldCode = new Foo();
DoSomething(oldCode);
// ...is **very** different to this code
var newCode = new Foo();
DoSomething(newCode);

1
(詳細については、これが暗黙の型変換であるすべての場所で同様の問題が発生する可能性があります)
Marc Gravell

1
同じ行で2度見たくない部分に同意しないでください。将来、宣言後に変数を直接作成しない可能性があります(たとえば、定義の下にある場合)。タイプが何であるかを直接明確にしない可能性があります。ほとんどの開発者は、特にコードの読み取りを困難にしたくない複雑なコードでは、行の先頭で直接型を確認するのに慣れています。
ゲルトジャン、

@TheVillageIdiot-編集をロールバックしました。この場合、hscrollはポイントに関連しているためです;-p
Marc Gravell

2
@Gertjan-私の脳は限られています。複雑な場合は、2回見たくないので、比較を開始する必要があります(インターフェース/コンクリート/その他)。一度見て、「ひとつに分類された」と思って嬉しいです。
Marc Gravell

17

varが難しい1つの特定のケース:オフラインのコードレビュー、特に紙で行われたもの。

そのためのマウスオーバーに依存することはできません。


17
なぜ紙の上でコードレビューをしているのですか?木について考えてみてください。;)
ダストマン

8
varを使用しなくても同じ問題が発生する可能性があります。問題はvarではありません。問題は不正な変数名です。変数名が適切に選択されている場合、varの使用は重要ではありません。
ライアンランディ

私のチームには、自分のコードを印刷して自分のコードをレビューし、バグを探す人がいます。彼の壁はコードで覆われています。私はかつて歩いて入ると、彼は大きなホワイトボード全体を1つのデバッグ演習で覆っていました。それはおそらく〜10000 LOCでした
ビープ音

タイプが名前の一部であるハンガリー語表記に戻らない限り、変数名だけでは問題は解決しません。
ケビンゲイル2010

17

大したことは何だかわかりません。

var something = someMethod(); // Type of 'something' not clear <-- not to the compiler!

あなたはまだ「何か」について完全なインテリセンスを持っています、そして曖昧なケースのためにあなたはユニットテストを持っていますよね?( あなたは? )

これはvarcharではなく、薄暗くなく、動的な型付けや弱い型付けではありません。次のようにマドンを停止しています:

List<somethinglongtypename> v = new List<somethinglongtypename>();

そして、その全体的な混乱を次のように減らします。

var v = new List<somethinglongtypename>();

いいですね、それほどいいわけではありません:

v = List<somethinglongtypename>();

しかし、それがブーの目的です。


「何か」のタイプはコンパイラーにとって非常に明確です。「var」は「someMethod」の戻り値のタイプに設定されます。それはコンパイラーにとっては明らかですが、プロジェクトに取り組んでいる開発者にとっては明らかではない場合があります。ブーは私に急速に成長しています。
stephenbayer 2008

いいえ、v = List<somethinglongtypename>();もっと良くはありません。新しい変数の導入と既存の変数への割り当てを区別することが重要です。
HighCommander4 2012年

現在のスコープで以前に 'v'に割り当てていた場合は、既存のスコープへの割り当てです。それ以外の場合は、新しい変数「v」への割り当てです。簡単です。
Frep D-Oronge 2012年

17

var「タイプを計算する」ことを望まないために誰かがキーワードを使用している場合、それは間違いなく間違った理由です。のvarダイナミック型の変数を作成していないキーワードが、コンパイラは、まだタイプを知っている必要があります。変数は常に特定の型を持っているので、可能であれば、型もコードで明確にする必要があります。

varキーワードを使用する正当な理由は次のとおりです。

  • 必要な場所、つまり匿名型の参照を宣言する場合。
  • それがコードをより読みやすくする場所、すなわち繰り返しの宣言を削除します。

データ型を書き出すと、コードがわかりやすくなります。これは、使用しているデータ型を示しているため、最初にコードが何をするかを理解することによってデータ型を理解する必要はありません。


11

Intellisenseが現在どの程度強力であるかを考えると、varが、クラスのメンバー変数や、表示されている画面領域外で定義されているメソッドのローカル変数よりも読みにくいかどうかはわかりません。

次のようなコード行がある場合

IDictionary<BigClassName, SomeOtherBigClassName> nameDictionary = new Dictionary<BigClassName, SomeOtherBigClassName>();

Isは次の場合よりもはるかに簡単または読みにくくなっています。

var nameDictionary = new Dictionary<BigClassName, SomeOtherBigClassName>();

私は実際にはこれを考慮しませんでした。それは、他の質問から、それをもう一度使用するのがかなり強力な点であると思われるからです。
Finglas、

それは基本的に、彼らはそれを実装する唯一の理由だった(匿名型を宣言することができることに加えて、彼らは「VAR」だけ匿名型のためだった特別なキーワードを作った可能性があります。)
MQP

10

VARの重要な点は、適切な場所でのみ使用することです。つまり、Linqでそれを容易にする(そしておそらく他の場合でも)ことを行うときです。

あなたはしている場合ですに何かのタイプあるは、それを使用する必要があります-そうしないのは単純な遅延です(一般的に推奨される創造的な遅延とは対照的です)-優れたプログラマーは、怠惰になるために非常に熱心に働き、検討することができますそもそものものの出所)。

全面禁止は、そもそも構成を乱用するのと同じくらい悪いですが、賢明なコーディング標準が必要です。

覚えておくべき他の事は、それが種類を変更できないということで、そのことVBの型varがあることである-それはある強く型付けされた変数の型が(推測されるだけというこれまでその不合理ではないと主張しているだろう人がいる理由でありますたとえば、foreachで使用しますが、可読性と保守性の両方の理由で同意しません)。

これは実行されると思います(-:

マーフ


10

確かにint簡単ですが、変数の型がのIEnumerable<MyStupidLongNamedGenericClass<int, string>>場合、varを使用すると処理が簡単になります。


2
+1。 intvarは気になるところですが、複数のネストされたジェネリック型varは天の恵みになります。これは、型名を何度も何度も使用すると、コードの可読性が実際に破壊される場所です。
Chris Farmer、

これは絶対にそれを使用する間違った理由です。コードがネストされたジェネリック型を使用する場合は、その特定の名前付きクラスを派生させる必要があります。例:class IntStringEnumerator : IEnumerable<MyStupidLongNamedGenericClass<int, string>>次に、新しい名前を使用します。これにより、コードがクリーンアップされ、タイプがわかりやすくなります。
xxbbcc

わかりましたが、私の例は単なる誇張でした。IntStringEnumerator i = new IntStringEnumerator()まだタイピングが多すぎます。
Blorgbeardは

9

CodingHorrorのこの問題に関する投稿から盗まれた:


残念ながら、あなたと他のすべての人はかなり間違っています。冗長性は良いことではないと私はあなたに同意しますが、この問題を解決するより良い方法は、次のようなことをすることでした:

MyObject m = new();

または、パラメータを渡す場合:

人物p = new( "FirstName"、 "LastName);

新しいオブジェクトの作成では、コンパイラーはタイプを右側からではなく左側から推測します。これは、フィールド宣言でも使用できるという点で、「var」よりも他の利点があります(他にもいくつかの領域があり、これも役立つ可能性がありますが、ここでは説明しません)。

結局、それは冗長性を減らすことを意図していませんでした。誤解しないでください。 "var"はC#では匿名のタイプ/プロジェクションにとって非常に重要ですが、ここでの使用は、そのタイプを難読化するので、WAY off(そして私はこれを長い間ずっと言ってきました)です。使用されています。2回入力する必要はあまりにも多いですが、0回宣言することは少なすぎます。

Nicholas Paldino .NET / C#MVP(2008年6月20日08:00 AM)


私はあなたの主な関心がより少なくタイプする必要があることであると思います-それからあなたはそれを使用することからあなたを揺るがすつもりであるどんな議論もありません。

あなただけしようとしている場合は、これまであなたのコードを見た人は、心配事も?そうでなければ、このような場合:

var people = Managers.People

大丈夫ですが、このような場合:

var fc = Factory.Run();

それは私の脳がコードの「英語」から形成し始める可能性があるあらゆる即時型推論を短絡します。

それ以外の場合は、プロジェクトで作業する必要がある可能性のある他の人に対して、最善の判断とプログラミングの「礼儀」を使用してください。


4
上記の例は、varを使用しないことを主張するものではありません。それらは、わかりやすい変数名を使用するための引数です。[var fc = Factory.Run();]の代わりに[bool fc = Factory.Run();]を使用した場合、コードは明確になりません。
ライアンランディ

9

var明示的な型の代わりに使用すると、リファクタリングがはるかに簡単になります(したがって、これが違いをもたらさなかったか、純粋に「構文上の砂糖」だったという以前のポスターと矛盾する必要があります)。

このメソッドが呼び出されるすべてのファイルを変更せずに、メソッドの戻りタイプを変更できます。想像してみて

...
List<MyClass> SomeMethod() { ... }
...

のように使用されます

...
IList<MyClass> list = obj.SomeMethod();
foreach (MyClass c in list)
  System.Console.WriteLine(c.ToString());
...

SomeMethod()を返すようにリファクタリングしたい場合はIEnumerable<MySecondClass>、変数宣言を変更する必要があります(これもforeach場合は、メソッドを使用したすべての場所で)ます。

あなたが書くなら

...
var list = obj.SomeMethod();
foreach (var element in list)
  System.Console.WriteLine(element.ToString());
...

代わりに、変更する必要はありません。


同意した-なぜこの素晴らしい副作用が、より人気のある応答で他のより主観的なプロの一部ほど宣伝されていないのか疑問に思っています。
fieldingmellish

今日私に起こった。MainMenuクラスのインスタンスを返すファクトリクラスがあります。今日、私はMainMenuと同じインターフェイスを持つMainMenu2を作成しました。変更後、すべてのアプリコードをそのままにしておきます!
Marco Staffoli 2010年

8

@aku:1つの例はコードレビューです。別の例は、シナリオのリファクタリングです。

基本的に、マウスでタイプハンティングをしたくありません。利用できない場合があります。


2
興味深いことに、varを使用するとリファクタリングが簡単になるためです。varを使用したことがある場合、その必要はありません。これで、常にIDEのリファクタリングツールに依存することができますが、タイプについては常にIDEに依存することもできます:)
Fred

8

それは好みの問題です。変数のに関するこの面倒なことは、動的に型付けされた言語に慣れると消えます。つまり、場合あなたが彼らのように起動する(誰もができれば、私はわからないんだけど、私がやります)。

C#varは動的型付けのように見えるという点でかなりクールですが、実際には静的型付けです-コンパイラーは正しい使用法を強制します。

変数の型はそれほど重要ではありません(これは以前に述べられています)。期待していない- (他の変数やメソッドとの相互作用)と、その名前が文脈から比較的明確にする必要がありCUSTOMERLISTが含まれてint...

私は上司がこの問題についてどう思うかをまだ見守っています。3.5で新しい構成を使用するために、「先に進む」という毛布を手に入れましたが、メンテナンスについてはどうしますか?


7

あなたの比較では IEnumerable<int>IEnumerable<double>心配する必要はありません。間違った型を渡しても、コードはコンパイルされません。

次のように、型安全性について心配する必要はありません。 var動的ではないのではありません。それは単なるコンパイラの魔法であり、あなたが作るどんなタイプの安全でない呼び出しも捕らえられるでしょう。

Var Linqには絶対に必要です。

var anonEnumeration =
    from post in AllPosts()
    where post.Date > oldDate
    let author = GetAuthor( post.AuthorId )
    select new { 
        PostName = post.Name, 
        post.Date, 
        AuthorName = author.Name
    };

インテリセンスでanonEnumerationを見ると、次のように表示されますIEnumerable<'a>

foreach( var item in anonEnumeration ) 
{
    //VS knows the type
    item.PostName; //you'll get intellisense here

    //you still have type safety
    item.ItemId;   //will throw a compiler exception
}

C#コンパイラはかなり賢いです-別々に生成された匿名型は、それらのプロパティが一致する場合、同じ生成型になります。

それ以外では、あなたがインテリセンスを持っている限りvar、コンテキストが明確なところならどこでも使うのは理にかなっています。

//less typing, this is good
var myList = new List<UnreasonablyLongClassName>();

//also good - I can't be mistaken on type
var anotherList = GetAllOfSomeItem();

//but not here - probably best to leave single value types declared
var decimalNum = 123.456m;

IQueriable<T>繰り返す前に削除してください: anonEnumeration.ToList();
David Diez 2013年

@DavidDiez言い換えれば?あなたの発言は意味がありません。私のコードスニペットのリファレンスIQueryableまたは.ToList()
キース

var anonEnumeration = from post in AllPosts() where post.Date > oldDate let author = GetAuthor( post.AuthorId ) select new { PostName = post.Name, post.Date, AuthorName = author.Name };IQueriable<T>?を返さない
David Diez 2013年

1
@DavidDiezそれは何をAllPosts()返すかに依存します- 質問者が参照するList<T>ので私はそれを仮定しました。その場合、結果はanonEnumerationのタイプになりIEnumerable<'a>ます。代わりにreturn がAllPosts()返された場合(Queryableにはないことに注意してください)-ただし、その場合、がを実装しいるため、コードは引き続き機能します。それらの違いについては、ここでより良いQ&Aがたくさんあります-私の場合は匿名であり、静的に型付けされた変数に割り当てることができます。IQueryable<T>anonEnumerationIQueryable<'a>iIQueryable<T>IEnumerable<T>'avar
キース

ああ、わかりました。説明してくれてありがとう:)私のコメントは、反復のIQueryable<T>たびにDBでreadステートメントを作成しているため、を繰り返すのは良い習慣ではないためです。*.ToList() IQueryable<T>それらを反復する前ににあることを確認してください
David Diez

7

それはあなたの視点によると思います。私は個人的に、var「誤用」のためにコードの一部を理解するのに困難を感じたことはありませんでした。同僚と私は、コードをかなり頻繁に使用しています。(この点でIntellisenseは大きな助けとなることに同意します。)繰り返しの残骸を取り除く方法としてそれを歓迎します。

結局のところ、ステートメントが

var index = 5; // this is supposed to be bad

var firstEligibleObject = FetchSomething(); // oh no what type is it
                                            // i am going to die if i don't know

対処するのが本当に不可能だったので、動的型付け言語を使用する人は誰もいなかったでしょう。


おそらく動的タイプが一般的な場所である.Net 4では、これはより重要になりますか?
Colin Desmond、

2
逆に、「var」で混乱している場合は、「dynamic」で混乱することを期待しています。神はだれでも動的を宣言し、「var」を使用してそれを参照することを禁止します:)
mqp

ダイナミックd = 52のようなものを意味しました。var x = d; 大丈夫なはずです。
mqp 09

7

どのタイプが使用されているかが明らかな場合にのみ、varを使用します。

たとえば、この場合はvarを使用します。これは、xのタイプが「MyClass」になることがすぐにわかるためです。

var x = new MyClass();

このような場合はvarを使用しません。コードの上にマウスをドラッグし、ツールチップを見てMyFunctionが返す型を確認する必要があるためです。

var x = MyClass.MyFunction();

特に、私は決して右サイドにも方法が、唯一の値ではない場合にVARを使用していません。

var x = 5;

(コンパイラが、バイト、ショート、整数などが必要かどうかを認識できないため)


の使用を正当化するのに十分なほど右側が明確でない場合var、それvarは問題ではありません。右側が問題です。十分に説明的ではありません。Customer c = GetContext()まだ不明確で、を使用するよりも優れていvarます。
JulianR

6

私にとっては、var.NETのバイリンガリズムが重要である理由に対する反感は、VB .NETも使用したC#プログラマにとって、その利点varは直感的に明らかです。以下の標準C#宣言:

List<string> whatever = new List<string>();

VB .NETでは、次のように入力するのと同じです。

Dim whatever As List(Of String) = New List(Of String)

ただし、VB .NETでは誰もそれを行いません。.NETの最初のバージョン以降、これを行うことができたので、それは愚かなことです...

Dim whatever As New List(Of String)

...変数を作成し、合理的にコンパクトな1行ですべて初期化します。ああ、でもが必要な場合IList<string>List<string>どうですか?さて、VB .NETでは、これを行う必要があります。

Dim whatever As IList(Of String) = New List(Of String)

あなたがC#でやらなければならないのと同じように、明らかに以下のために使用できませんvarでした:

IList<string> whatever = new List<string>();

タイプが異なるものである必要がある場合は、それが可能です。しかし、優れたプログラミングの基本原則の1つは冗長性を減らすことです。それがまさにvarの役割です。


1
おかしいと思いますが、バイリンガリズムはvarの使用を促進するものです。varキーワードに対する私の対立は、JavaScriptの流暢さに直接由来します。:)
urig

varC#ではvarJavaScript とは何の関係もありません。varC#での-declared変数は強く型付けされています。
Ryan Lundy 2010

6

匿名型に使用します-それが目的です。それ以外のものは使いすぎです。Cで育った多くの人々のように、型の宣言の左側を見るのに慣れています。必要がない限り、私は右側を見ません。var古い宣言に使用すると、いつでもそれができるようになり、個人的には不快に感じます。

「問題ではないので、満足しているものを使用してください」と言っている人は、全体像を見ていません。誰もがどこかで他の人のコードを拾い、彼らがそれを書いたときに彼らが行ったどんな決定にも対処しなければなりません。まったく違うvarものをミックスに追加せずに、根本的に異なる命名規則や-古典的な不満-筋交いのスタイルに対処しなければならないのは十分に悪いことです。最悪のケースは、1人のプログラマが使用しなかった場合でvar、それを気に入って、それを使用してコードを拡張するメンテナがやって来るでしょう。だから今、あなたは不道徳な混乱を持っています。

標準は、ランダムなコードを拾い、それをすばやく処理できる可能性がはるかに高いという意味で、まさに良いものです。違いが多いほど、難しくなります。そして、「var everywhere」スタイルに移行すると、大きな違いが生まれます。

私は動的なタイピングを気にしませんし、暗黙のタイピングを気にしません-それらのために設計された言語で。私はPythonがとても好きです。しかし、C#は静的に明示的に型付けされた言語として設計されており、それが維持されるべきです。匿名型のルールを破ることは十分に悪いことでした。人々にそれをさらに受け入れさせ、言語のイディオムをさらに破らせることは私が不満なことです。魔神がボトルからなくなったので、二度と戻らないでしょう。C#はキャンプにバルカン化されます。良くない。


7
ワオ。これまでにこのスレッドで出されたすべての議論を無視し、議論全体を再設定することは、かなりの成果です。
Konrad Rudolph

この100%は、特に誰かのコードを拾うという観点から、「var」について私がどのように感じているかを説明しています。varを使用すると、散らかっている場合、手元のタスクが根本的に変わります。+1
Simon、

6

テスト中に何度も、私は自分が次のようなコードを持っていることに気づきます:

var something = myObject.SomeProperty.SomeOtherThing.CallMethod();
Console.WriteLine(something);

さて、時々、SomeOtherThing自体が何を含んでいるかを見たいと思います。SomeOtherThingはCallMethod()が返すのと同じ型ではありません。ただし、varを使用しているので、これを変更するだけです。

var something = myObject.SomeProperty.SomeOtherThing.CallMethod();

これに:

var something = myObject.SomeProperty.SomeOtherThing;

varがないと、左側の宣言された型も変更し続ける必要があります。私はそれがマイナーであることを知っていますが、それは非常に便利です。


6

var時間を節約できると考える愛好家にとって、入力するのに必要なキーストロークは少なくなります。

StringBuilder sb = new StringBuilder();

より

var sb = new StringBuilder();

私を信じないならemを数えて...

19対21

必要に応じて説明しますが、試してみてください...(インテリセンスの現在の状態によっては、それぞれについてさらに2つ入力する必要がある場合があります)

そしてそれはあなたが考えることができるすべてのタイプに当てはまります!!

私の個人的な感覚では、コードでの認識の読みやすさが低下するため、タイプが不明な場合を除いて、varを使用しないでください。完全なラインよりもタイプを認識するのに脳が長くかかります。マシンのコードとビットを理解している古いタイマーは、私が何を話しているかを正確に知っています。脳は並行して処理し、varを使用すると、入力をシリアル化するように強制されます。なぜ誰もが自分の脳をより強く働かせたいのでしょうか?それがコンピュータの目的です。


stringBuilder sb = new StringBuilder()の繰り返しは、はっきりと認識するのが面倒で時間がかかります。それは余分なノイズです。問題は、一部のコードを理解するために余分な知的努力を行うかどうかを決定することは、かなり主観的なことです。
ljs

「varは、型がわからない場合以外は使用しないでください...」-コンパイラと同様に、常に型を知ることができます。これは動的型付けではなく、コンパイラーが型を判別できるようにするだけです。ただし、タイプが不明になることはありません。
ガブリエルマガナ2010年

5

varをすべての場所で分割します。私にとって問題のある場所は、内部のshort型だけです。たとえばint i = 3;var i = 3;


5

昨日書いたコードから、それは確かに物事をより簡単にすることができます:

var content  = new Queue<Pair<Regex, Func<string, bool>>>();
...
foreach (var entry in content) { ... }

これがないと、非常に冗長になりvarます。

補遺:実際の型推論を備えた言語(F#など)で少し時間をかけると、コンパイラーが式の型を正しく理解するのにどれだけ優れているかがわかります。それは確かにvar私ができる限り使用する傾向があることを意味しており、明示的な型を使用すると、変数が初期化式の型ではないことが示されます。


うん、コンパイラは私たちよりも賢いです、それを乗り越えてください!
Benjol 2009

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.