なぜvarは悪いことなのでしょうか?
-
23-08-2019 - |
質問
先日同僚とチャットしていて、彼らのコーディング標準では明示的に var
C#のキーワード。彼らはなぜそうなるのか全く分かりませんでしたが、私はコーディングの際に暗黙の宣言が非常に便利であることを常に感じてきました。変数の型を見つけるのに問題があったことはありません (VS で変数にカーソルを置くだけで、そのようにして型を取得できます)。
C# で var キーワードを使用することがなぜ悪い考えなのか知っている人はいますか?
解決
.NET Frameworkの設計ガイドラインの(素晴らしいブック)は2008年11月に出てきたタイプが明らかと明確なときvar
を使用して検討をお勧めします。
が、一方で、アントンGogolevが指摘したように、コードを読むときにあいまいさにつながるvar
を使用している場合、それはそれを使用しない方が良いです。
ブック(附属書A)で、彼らは実際にこの例を与えます:
var names = new List<string>(); // good usage of var
string source = GetSource();
var tokens = source.Split(' '); // ok; most developers know String.Split
var id = GetId(); // Probably not good; it's not clear what the type of id is
これは可読性が卑しい開発者の気まぐれにさらされていないことを確認するために、あなたの組織は、あなたがvar
の価値がありませんでしたし、それを禁止することを決めた、ということが可能です。
それはあなたの処分で素敵なツールを持つが、ロックされたガラスのキャビネットにそれを維持するようなものだ、しかし残念だ。
は、ほとんどの場合、単純型のためvar
を使用して、実際に読みやすさを助け、我々はまた、var
を使用するためのパフォーマンス上のペナルティがないことを忘れてはならない。
他のヒント
var q = GetQValue();
確かに悪いことです。しかし、
var persistenceManager = ServiceLocator.Resolve<IPersistenceManager>();
私にはまったく問題あります。
bottomlineは次のとおりです。説明的な識別子名を使用し、あなただけの罰金に沿って取得します。
。追記として:私はvar
キーワードを使用することを許可されていないとき、彼らは匿名型の対処はどうすればよいのだろうか。それとも、彼らは完全にそれらを使用しないのですか?
ほとんどの場合、賢明に使用すると (つまり、型と値が同じ単純な型初期化子)であれば、問題ありません。
変更によって問題が発生したかどうかが不明確な場合があります。主に、初期化された型と (元の) 変数の型が同じではない場合です。次の理由が考えられます。
- 変数はもともと基底クラスでした
- 変数はもともとインターフェイスでした
- 変数はもともと暗黙的な変換演算子を備えた別の型でした
このような場合、型解決で問題が発生する可能性があります。たとえば、次のとおりです。
- 競合する 2 つの型に対して異なるオーバーロードを持つメソッド
- 2 つの競合する型に対して異なるように定義された拡張メソッド
- いずれかの型で再宣言された (非表示になった) メンバー
- ジェネリック型の推論は異なる動作をします
- オペレータの解決は異なる動作をします
このような場合は、コードの意味を変更して、別のものを実行します。それでは、これは悪いことです。
例:
暗黙的な変換:
static void Main() {
long x = 17;
Foo(x);
var y = 17;
Foo(y); // boom
}
static void Foo(long value)
{ Console.WriteLine(value); }
static void Foo(int value) {
throw new NotImplementedException(); }
メソッドの隠蔽:
static void Main() {
Foo x = new Bar();
x.Go();
var y = new Bar();
y.Go(); // boom
}
class Foo {
public void Go() { Console.WriteLine("Hi"); }
}
class Bar : Foo {
public new void Go() { throw new NotImplementedException(); }
}
等
確かにこれは間違いです。一部の民族は、それが実際に強く型付けされたことを認識し、そして全くVBでのVARのようにしていないからです。
すべての企業コーディング標準は意味がありませ、私は一度、会社の名前を持つすべてのクラス名を接頭辞と思った会社で働いていました。同社は、それが名前だ変更大規模な手直しがありました。
まず、原則として、コーディング標準はチームによって議論され、合意されるべきであり、その背後にある理由を文書化して、なぜそのコーディング標準が存在するのかを誰でもわかるようにする必要があります。それらは一人のマスターからの聖なる真理であるべきではありません。
第二に、このルールはおそらく正当化されます。 コードは書かれた回数よりも読まれた回数の方が多い. var
書き込み速度は向上しますが、読み取り速度が少し遅くなる可能性があります。これは明らかに、「常に変数を初期化する」のようなコードの動作規則ではありません。なぜなら、2 つの選択肢 ( var
と型の書き込み)はまったく同じ動作をします。したがって、これは重要なルールではありません。禁止はしません var
, 私なら「Prefer...」を使います。
数か月前にこのトピックに関するブログ記事を書きました。私の場合、可能な限りこれを使用し、特に型推論を中心に API を設計しています。私が型推論を使用する基本的な理由は次のとおりです。
- 型の安全性は低下しません
- 実際、暗黙的なキャストを警告することで、コード内の型の安全性が向上します。foreach ステートメントの最良の例
- C# で DRY 原則を維持します。これは申告の場合に特化したものですが、なぜわざわざ名前を 2 回言うのでしょうか?
- 場合によっては、完全に必要です。匿名型の例
- 機能を損なうことなく、入力回数を減らします。
http://blogs.msdn.com/jaredpar/archive/2008/09/09/when-to-use-type-inference.aspx
var
は、最新の「あなたの中括弧のレイアウト方法」/ハンガリアン記法/キャメルケースの議論です。正解はありませんが、極端に座る人々がいます。
あなたの友人は、彼らが過激派の1未満に働くだけ残念なことです。
それは完全に(あなたがより多くのLINQを使うと非常に便利になる)匿名型の使用を禁止する意味禁止は。
誰かが匿名型を使用しないための良い理由を形式化することができない限り、これは無地でシンプルな愚かである。
これは、読みやすさを傷つけることができます。しかし、完全にあなたの同僚がそれなしで匿名型を使用して大変な時間を持つことになりますと、それは少し奇妙である禁じるます。
これは本当にあなたのコードで読みやすさの問題です。
私の個人的な好みは(あなたがすべてで匿名型を使用したい場合、あなたはVARを使用する必要があります、確かに)これまで匿名型のための「VAR」を使用し、これらは主にLINQクエリから来るだけにあります。これらのケースでは、あなたのクエリを入力します。
新しい(暗黙&匿名)に突出している場合は、VARを使用するしかありませんしかし、C#3.0は喜んで、あなたが好きなあなたはどこでもVARを使用できるようになるLINQと匿名型の外、例えばます:
var myint = 0;
var mystring = "";
は、完全に有効である、とミンとのMyStringは、それらを初期化するために使用される推定された値によって強く型付けされます。 (従って、ミンが可能System.Int32とのMyStringが可能System.Stringです)。彼らは暗黙的に型付けされますどのような種類の変数を初期化するために使用される値を見たときにもちろん、それはしかし、私は上記のように書かれていた場合には、コードの可読性のためのより良いことだと思う、かなり明白です:
int myint = 0;
string mystring = "";
あなたが一目ですぐに見ることができるので、正確にこれらの変数があるどの種類ます。
このやや混乱のシナリオを考えます:
var aaa = 0;
double bbb = 0;
完全に有効なコード(少し型破りな場合)が、上記では、私はBBBはint型であることを、しかし、AAAは間違いなくダブルではなく、int型ではありません表示されて初期化した値にもかかわらず、二重であることを知っています。
C# は Microsoft の言語であるため、Microsoft の意見が適切であると考えることもできます。
「ただし、 変数 少なくとも、コードが他の開発者にとって理解しにくくなる可能性はあります。このため、C# ドキュメントでは通常、 変数 必要な場合のみ。」
見る MSDN - 暗黙的に型指定されたローカル変数 (C# プログラミング ガイド), 、最後の段落。
また、次のことにも注意する必要があります。 変数 初期代入時のコンパイル時のデータ型テストを削除します。
var x = "mistake"; // error not found by compiler
int x = "mistake"; // error found
ほとんどの変数は 1 回だけ割り当てられるため、一貫して使用する必要があります。 変数 変数割り当てに関するほとんどすべてのデータ型テストを削除します。
これにより、コードが偶発的な変更に対して脆弱になります。マージツールや疲れた開発者によって作られたもの。
暗黙の型宣言は素晴らしいです、そしてフラットアウトの人々は、それが生産性を損傷し、脆いコードを招待禁止します。
これは、ほとんどのリファクタリング時に非常に便利であるタイプセーフ、コンパイラがチェックダックタイピング、のようなものです。私はリストを返すメソッドを持っている、と私はそれがIEnumerableを返すようにリファクタリングた場合、その後、varキーワードを使用し、唯一のIEnumerableメソッドを使用しているそのメソッドへの発信者は罰金になります。私は明示的に指定している場合、例えば、リストは、その後、私はどこでもIEnumerableをすることを行くと変えるようになってきました。
暗黙の-入力する発信者のいずれかがリストのメソッドが必要な場合は明らかに、私は私が構築したときにコンパイルエラーを取得しますが、そのような場合、私はおそらく、とにかく戻り値の型を変更されていないはずです。
エリック・リッパート それをうまく要約します:
- 必要な場合は var を使用してください。匿名型を使用している場合。
- 宣言の型が初期化子から明らかな場合、特にオブジェクトの作成の場合は、var を使用します。これにより冗長性が排除されます。
- コードが変数のセマンティックな「ビジネス目的」を強調し、そのストレージの「機械的」詳細を軽視する場合は、var の使用を検討してください。
- コードを正しく理解して維持するために必要な場合は、明示的な型を使用してください。
- 「var」を使用するかどうかに関係なく、わかりやすい変数名を使用してください。変数名は、変数の記憶域の詳細ではなく、変数のセマンティクスを表す必要があります。「decimalRate」は正しくありません。「金利」は良いですね。
私自身の意見:次のような型は読みにくく、少し無意味だと思います。 int
, string
, bool
あるいは User
. 。結局のところ、読みやすさが重要なので (LINQ で使用する場合を除く)、var が散在すると読みにくくなり、言語設計者が意図したキーワードの目的が損なわれる可能性があります。
私は例があったいくつかの基底クラスの型されるのではなく、実際のDataRowタイプになりました。それは私がVARとのトラブルがあった時だけです。
「var」は明確にすることを意味します
を使用するかどうかに関する主な議論は、 var
キーワードがあるかどうかは、あなたや他の開発者にとってコードがどれだけ読みやすいかによって決まります。
物語を書くのと同じように、決定的な正解はありません。しかし、これを平易な英語でいくつか例を見てみましょう。
ジェイクはビルに挨拶しました。彼は気に入らなかったので、向きを変えて反対方向に行きました。
誰が反対方向に行きましたか?ジェイクかビル?この場合、「Jake」と「Bill」はタイプ名のようなものです。そして、「彼」と「彼」は var キーワードのようなものです。この場合、より具体的にすることが役立つかもしれません。たとえば、次の例はより明確です。
ジェイクはビルに挨拶しました。ジェイクはビルが気に入らなかったので、背を向けて向こうへ行ってしまいました。
この場合、より具体的にすることで文章がより明確になります。しかし、常にそうとは限りません。場合によっては、具体的であると読みにくくなります。
ビルは本が好きなので、ビルは図書館に行き、ビルはずっと好きだった本を取り出しました。
この場合、「彼」を使用し、場合によっては彼の名前をまとめて省略した方が文が読みやすくなります。これは、 var
キーワード。
ビルは本が好きなので、図書館に行って、ずっと好きだった本を取り出しました。
これらのたとえは要点をカバーしていますが、ストーリー全体を伝えているわけではありません。これらの例を見ると、人を指す方法が 1 つしかありませんでした。Bill などの名前を使用するか、「彼」や「彼」などのより一般的な方法で使用します。しかし、私たちが取り組んでいるのはたった 1 つの単語だけです。
コードの場合、型と変数名という 2 つの「単語」があります。
Person p = GetPerson();
ここで問題となるのは、何が何であるかを簡単に判断できるだけの十分な情報がそこにあるのかということです。 p
は?このシナリオの中で人々がどのような人物であるかまだわかりますか:
var p = GetPerson();
これはどう:
var p = Get();
これはどう:
var person = Get();
またはこれ:
var t = GetPerson();
またはこれ:
var u = Person.Get();
キーワードかどうか var
特定のシナリオで機能するかどうかは、コードの複雑さだけでなく、変数、クラス、メソッドの名前など、コードのコンテキストに大きく依存します。
個人的によく使うのは、 var
より包括的なキーワード 自分. 。ただし、私は変数に型にちなんで名前を付ける傾向があるので、実際に情報が失われることはありません。
そうは言っても、時には例外を作ることもあります。複雑なものにはそれがあり、ソフトウェアは複雑でなければ何でもありません。
ここでは、私は、明示的な型付け対var
の効率に実行されたテストの結果があります:
private void btnVar_Click(object sender, EventArgs e)
{
Stopwatch obj = new Stopwatch();
obj.Start();
var test = "Test";
test.GetType();
obj.Stop();
lblResults.Text = obj.Elapsed.ToString();
}
private void btnString_Click(object sender, EventArgs e)
{
Stopwatch obj = new Stopwatch();
obj.Start();
string test = "Test";
obj.Stop();
lblResults.Text = obj.Elapsed.ToString();
}
まずラベルの結果は00:00:00 000034
第2ラベル結果は00:00:00 00008