web-dev-qa-db-ja.com

使用するもの:varまたはオブジェクト名タイプ?

これは、プログラミングするときにいつも疑問に思う質問です。コードを書くときに何を使用するか:

var myFiles = Directory.GetFiles(fullPath);

または

string[] myFiles = Directory.GetFiles(fullPath);

varは新しく、暗黙的に型指定されたローカル変数なので、ローカルでしか使えず、nullにできないなどのルールがありますが、「普通に」使うメリットはあるのでしょうか。

「通常」の部分は、匿名タイプオブジェクトおよびコレクションの初期化子およびクエリ式ではなく、varanonymousを使用する意図があると述べています。オブジェクトなので、私が言いたいのは...上記の例のように。

あなたの考えは何ですか?

53
balexandre

LINQでのvarの明白な使用に加えて、読みやすさのためにヘアリー変数宣言を省略します。例:

var d = new Dictionary<string, Dictionary<string, Queue<SomeClass>>>();

一般に、私は静的型付けから一種の快適さを得て(より良いWordが必要なため)、それをあきらめたくありません。変数を宣言するときに自分が何をしているのかを知っているという感覚が好きです。変数を宣言することは、コンパイラーに何かを伝えるだけでなく、コードを読んでいる人に何かを伝えることでもあります。

例を挙げましょう。 List<string>を返すメソッドがあるとします。このコードは確かに正しいので、C#開発者の90%がおそらくそれを書く方法だと思います。

List<string> list = MyMethod();

明らかに、そうですか?実際、ここにvarを簡単に使用できる場所があります。

十分に真実です。しかし、thisバージョンのコードは、変数を宣言するだけでなく、それを書いた人が何をしようとしているのかを教えてくれます。

IEnumerable<string> list = MyMethod();

そのコードを書いた開発者は、「このリストを変更するつもりはなく、そのメンバーにアクセスするためにインデックスを使用するつもりもありません。私がするのは、リスト全体を繰り返すことだけです」と言っています。これは、1行のコードで理解できる多くの情報です。 varを使用すると、あきらめることになります。

もちろん、そもそも使用していなかったとしても、あきらめることはありません。あなたがそのコード行を書くような開発者なら、そこでvarを使用しないことはすでに知っています。

編集:

Jon Skeetの投稿を読み直したところ、EricLippertからのこの引用が飛び出しました。

暗黙的に型指定されたローカルは、方法を強調せず、それによって何を強調することができる1つの小さな方法にすぎません。

実際、暗黙のタイピングを使用することは、実際には何を暗黙的に残すことになると思います。何にこだわらなくても大丈夫です。たとえば、次のようなLINQクエリを何気なく記述します。

var rows = from DataRow r in parentRow.GetChildRows(myRelation)
           where r.Field<bool>("Flag")
           orderby r.Field<int>("SortKey")
           select r;

そのコードを読んだとき、私が読んでいるときに思うことの1つは、「rowsIEnumerable<DataRow>です」です。 LINQクエリが返すのはIEnumerable<T>であることがわかっているので、そこで選択されているオブジェクトの種類を確認できます。

これは、が明示されていない場合です。推測するのは私に任されています。

さて、私がLINQを使用するケースの約90%では、これは少しでも問題ではありません。 90%の確率で、次のコード行は次のようになります。

foreach (DataRow r in rows)

しかし、rowsIEnumerable<DataRow>として宣言することが非常に役立つコードを想像するのは難しいことではありません-多くの異なる種類のオブジェクトが照会されていたコードであり、反復の横にあるクエリ宣言。IntelliSenseでrowsを検査できると便利です。そして、それはどのようにではなく、何であるかです。

61
Robert Rossney

これについては、「どこでもvarを使用する」から「基本的に必要な匿名タイプでのみvarを使用する」まで、さまざまな意見が寄せられます。私は好きです エリックリペットの見解

すべてのコードは抽象化されています。コードが「実際に」行っているのは、データを操作することですか?いいえ、数字ですか?ビット?いいえ。電圧?いいえ。電子?はい、しかし電子のレベルでコードを理解することは悪い考えです!コーディングの技術は、聴衆にとって適切なレベルの抽象化が何であるかを理解することです。

高水準言語では、コードが(意味的に)何をするかとコードがそれをどのように達成するかの間には常にこの緊張関係があります。メンテナンスプログラマーは、変更を加えることに成功するためには、何をどのように行うかを理解する必要があります。

LINQの要点は、「方法」を大幅に強調せず、「何」を大幅に強調することです。プログラマーは、クエリ内包表記を使用して、将来の聴衆に「この結果セットがどのように計算されるかを正確に知ることも気にすることもすべきではないと思いますが、結果セットのセマンティクスが何であるかを非常に気にする必要があります」と言っています。それらは、コードを実装されているビジネスプロセスに近づけ、コードを動かすビットや電子から遠ざけます。

暗黙的に型指定されたローカルは、方法を強調せず、それによって何を強調することができる1つの小さな方法にすぎません。それが特定の場合に行うべき正しいことであるかどうかは、判断の呼びかけです。したがって、型の知識が適切であり、その選択がメソッドの継続的な操作にとって重要である場合は、暗黙的な型指定を使用しないでください。明示的な入力では、「これがどのように機能するかを説明しています。注意してください」と表示されます。暗黙の入力では、「これがリストであるか顧客[]であるかは少し問題ではありません。重要なのは、顧客の集まりであるということです」と書かれています。

個人的には、タイプが合理的に明白でない場合は傾向がありません-LINQクエリを「合理的に明白」として含めます。たとえば、Directory.GetFiles(または完全に何か他のもの)の代わりにstring[]を返すことはあまり明白ではないので、私はFileInfo[]に対してそれをしません。後で行うこととの大きな違い。

代入演算子の右側にコンストラクター呼び出しがある場合は、varを使用する可能性がはるかに高くなります。型が何であるかは明白です。これは、複雑なジェネリック型で特に便利です。 Dictionary<string,List<int>>

41
Jon Skeet

個人的に私は2つの場所でのみvarを使用します:

  1. 匿名タイプの場合、つまり。 LINQ関連(場合によってはvarが必要な場合)
  2. ステートメントが同じタイプで特定のタイプを宣言および構築する場合

すなわち。これはポイント2の例です。

var names = new List<String>();

編集済み:これはJonSkeetの質問への回答です。

上記の答えは実際には単純化されています。基本的に、私はvarを使用します。ここで、タイプは次のいずれかです。

  1. 知る必要はありません(ただし、それほど多くの場所ではありません)
  2. 知ることができない(LINQ、匿名タイプ)
  3. それ以外の場合は既知、またはコードから明らか

ファクトリメソッドの場合、コードを書く場所で知っておく必要があるのは、返されるオブジェクトが何らかのタイプの子孫であり、あるタイプには静的ファクトリメソッドがあるので、varを使用します。このような:

var connection = DatabaseConnection.CreateFromConnectionString("...");

上記の例は、私のコードの実際の例です。少なくとも私とこのコードを使用する人々にとって、connectionはDatabaseConnectionの子孫であることは明らかですが、正確な型はどちらにも必要ありませんコードを理解することも、それを使用することもありません。

「どこでもvarを使用する」スタイルを試しました...そしてこれが私がそれを使い続けなかった理由です。

  1. 読みやすさが低下することがあります
  2. =の後にIntellisenseを制限します
  3. 「var」と入力することは、特にインテリセンスで「int」、「string」などを入力するよりも実際にはそれほど短くありませんでした。

そうは言っても、私はまだLINQで使用しています。

9
Inisheer

私はどこでもvarを使用する傾向がありますが、同僚は「やめなさい」と言いました。だから私は今、匿名型、LINQクエリ、そして右側のコンストラクターでのみvarを使用しています。

3

この post には、var型インターフェースまたはオブジェクト型をいつ使用するかについてのいくつかの良いガイドラインがあります。

3
Andres Denkberg

型推論がその日を支配する関数型プログラミングの土地から来て、私は可能な限りすべての地元の人々にvarを使用します。

Visual Studioでは、ローカルの種類が何か疑問に思っている場合は、マウスでそのローカルにカーソルを合わせるだけです。

3
yfeldblum

これがHaskellで通常どのように処理されるかに注目するのは興味深いと思います。 Curry-Howard同形 のおかげで、Haskellの式の(最も一般的な)型を推測できるため、いくつかの例外を除いて、型宣言は基本的にどこにも必要ありません。たとえば、タイプを推測されるよりも具体的なものに意図的に制限したい場合があります。

もちろん、必要なものと推奨されるものは同じものではありません。実際には、トップレベルの定義には常に型宣言があり、ローカライズされた定義には型宣言が省略されているという慣習があります。これは、ローカルの「ヘルパー」または「一時的な」定義の読みやすさとは対照的に、定義全体の読みやすさの明確さのバランスをうまく取っているようです。私が正しく理解していれば、そもそも「トップレベル」の定義(メソッドやグローバル関数など)にvarを使用することはできないので、これは「use var」に変換されると思います。 C#の世界で「どこでもできる」。もちろん、「int」と入力すると、「var」と同じキーストローク数になりますが、ほとんどの例ではそれより長くなります。

1
mithrandi