web-dev-qa-db-ja.com

「var」とnullの合体演算子「?」読みやすさを損なうことなく楽しまれる?

質問のタイトルは非常に主観的であることは知っていますが、同僚から??演算子の使用に直面しました。同時に、新しいコードでvarを適用することにあまり満足/快適ではありませんでした。

??演算子を使用するために指定された引数は、コードの読みやすさを奪っていました。

私の質問は、varを使い始めたときに同じことが起こりませんか?

23
Numan

ヌル合体演算子(??)

個人的には、この演算子を使用することの欠点は何もありません。 「簡単」から「複雑」な新しい演算子まで、次の3つのコードサンプルを検討してください。

魔法なし:

bool isNameSet = false;
string name;
if ( isNameSet )
{
    Console.WriteLine( name );
}
else
{
    Console.WriteLine( "No name set." );
}

三項演算子:

bool isNameSet = false;
string name;
Console.WriteLine( isNameSet ? name : "No name set." );

ヌル合体:

string name = null;
Console.WriteLine( name ?? "No name set." );

これらの演算子が発明された理由は、それらが非常に一般的なプログラミング操作を表すためです。慣れていないので使いたくないのはstubbornだけです。言語は進化し、機能は進化し、それらの使い方を学びます!

varキーワード

私はvarキーワードについて多少異なる意見を持っています。変数のタイプは、多くの場合、コードに関する追加情報を提供します。 varキーワードを使用してタイプを非表示にすると、コードが読みにくくなることがあります。自動補完を使用したり、識別子にカーソルを合わせて実際に何であるかを確認したりせずに、何が期待できるかがわかりません。私の意見では、これは読み取り/書き込みが遅いコードになります。

タイプが追加の情報を提供しないことがわかったときに、キーワードを使用します。

  • 主にin foreachループです。これは、Resharperからの設定なので、そこから学びました。ほとんどの場合、トラバースしているコレクションの種類を知っているので、そのコレクション内からのアイテムを期待していることがわかります。
  • Linqクエリ。 linqクエリの結果は、多くの場合、非常に複雑なジェネリック型です。このタイプを表示することは、良いことよりも害を及ぼします。
  • コンストラクターで単純に初期化される長い型名。コンストラクターを見ると、型が何であるかはすでにわかります。

最後のステートメントの例として:

ThisIsSomeSpecializedTypeRightHere duplication =
    new ThisIsSomeSpecializedTypeRightHere();
var justAsReadable =
    new ThisIsSomeSpecializedTypeRightHere();  // Less duplication.

// But I still prefer the following ...
int number = 9;
SomeCreatedType foo = Factory.CreateSomeType();
53
Steven Jeuris

varを使用すると、コードの冗長性が低下し、読みやすくなります。私の意見では、読みやすさは、表示される詳細の数ではなく、一見して非表示になっている詳細の数によって評価されるべきです。 Linqの例に加えて、次の例では、varはソースコードレベルでのダックタイピングを許可します。

...
foreach (var message in messages) {
  var label = Factory.CreateLabel();
  label.Text = message;
  Controls.Add(label);
}
...

Textプロパティを提供している限り、誰がラベルの種類を気にかけますか?

16
Codism

??演算子については、そのような演算子で言語を頻繁に使用したことがないため、重要なコメントはありません。 varについては、Ruby、Python、Perl、PHPなど、常に完全に暗黙の型指定が行われている言語でプログラミングします。これらの言語のネイティブは、変数の形式的な型を変数は何ができるかdo、つまりその構造/ダックインターフェースに興味があります。

同様に、私は主にDでプログラミングします。Dは静的に型付けされますが、autoキーワードがあり、これはvarと同等です。リーダーまたは(暗黙的な変換を介して)コンパイラーに対して何かのタイプを強調する特定の必要性がない限り、どこでもそれを使用することは慣用的と見なされています。関数の戻り値の型として使用される場合を除いて(これはDで許可されています)、読みやすさを妨げることはありませんでした。プログラムするときは、ほとんどの場合、形式的/主格的な型ではなく、構造/ダックインターフェイスの観点から考えるからです。

さらに、可能な限りvarを使用するIMHOは、DRYの良い例です。何かのタイプは1か所だけで指定する必要があり、伝播する必要があるときはいつでも自動的に伝播されます。 varを使用し、変数の正式な型をある時点で変更する必要がある場合、必要な変更は、プログラマーではなくプログラムがまだ型が正しい限り、コンパイラーが必要とするすべての場所に自動的に伝搬されます。すべてのインスタンスを手動で変更する必要があります。これはGood Thing(TM)です。

16
dsimcha

これは結局のところチームの問題だと思います。私のチームの他の誰にも読めない場合は、私はそれを使用しませんが、例を使って説得するために数回試すか、またはより読みやすいと思われる類似の略語(+ =など)を指摘することもできます。

しかし、一人で作業している場合、私は?? varは制限なく読みやすくなっています。でも

var a = b ?? c ?? d ?? e ?? "";

私にはかなり明白です。

もちろん、三項演算子とdynamicは別の問題です。

13
pdr

??を使用するための引数演算子は、コードの可読性を奪いました。

簡単に言えば、このコメントはコメントを書いた人に私に知らせてくれますが、理解するのが上手ではありません。これは特定の状況で最も当てはまる可能性がありますが、全体として、「読みやすさ」のためにC#チームが明らかに追加するのに十分重要であると明らかに思ったものは無視しません。これをif(boolean_object)if(boolean_object == true)の同じカテゴリに入れます。 2番目の方が読みやすいと主張する人もいますが、実際には、誰かが読み書きできるようにコードを追加しているだけで、状況によってはより混乱する可能性があります(if(boolean_object != false)と考えてください)。

私の質問は、varを使い始めたときに同じことが起こりませんか?

C#チームは、それがどうなるかを知っているものを定義しないことを許可しています。変数がどうなるかを絶対に定義する必要がない限り(返されるオブジェクトのタイプがxであることが絶対に重要であるか、またはそれが実際に読み取れない場合)、varを使用します。 var x = "MY_STRING";見てみると、これは文字列です。実は、私が必要なことをしている限り、文字列であることを気にしません。変数の型を定義することは、コンパイラーのためではなく、私の利益のためです。何か問題がある場合、変数タイプが間違っていると、コンパイラーは実行時にそれを知らせます。

10
kemiller2002

私の意見では、varキーワードは、最初に導入された状況であるLINQクエリで使用するのが最適です。これらのクエリでは、返される結果のタイプに、複雑な複雑な名前が含まれていることがよくあります。これは、事前に判別するのが難しく、読者がコードの機能を理解するのに役立ちません。

ただし、var text = "Some text " + variableName + "some more text."は単に怠惰です。

編集:@Jorgあなたは意図的に単純化した答えに飛びつきましたが、ディスカッションには何も追加しませんでした。わかりました、これをより良い例として:var items = doc.DocumentElement.FirstChild.ChildNodes;それからタイプがわかる場合は、クッキーを差し上げます。

0
Josh Earl

Varの使用に関して根本的な問題があります。

この例では、すべてが並んでいますが、問題は実際には共有ライブラリまたはプロジェクトを使用する大規模なソリューションにあります。

このことを考慮:

public MyFirstObject GetMeAnObject() {
    return new MyFirstObject();
}

public void MainProgram() {
    var theObject = GetMeAnObject();
    theObject.PerformOperation();
}

GetMeAnObjectが自分のニーズに合わせて誰かによって変更された場合はどうなりますか?

public MySecondObject GetMeAnObject() {
    return new MySecondObject();
}

MainProgramメソッドの.PerformOperation()で大きな赤いエラーが発生します。どうした?以前は、PerformOperationは完全に機能していました。 theObjectのメソッドを見ると、トレースなしで消えています。前回あったので、その方法が必要です。 MyFirstObjectにPerformOperationと呼ばれるメソッドがある場合、今では見えないため、長い時間をかけて尾を追跡し、その理由を解明しようとする可能性があります。 GetMeAnObjectがMyFirstObjectを返すことは誰もが「知っている」ので、それをチェックするポイントはありません。

TheObjectを明示的に入力した場合、GetMeAnObjectを呼び出す行に無効なキャストエラーが発生し、GetMeAnObjectが予期しない型を返していることは明らかです。

つまり、明示的な宣言は、エラーの意味を理解していることを意味します。無効なキャストは、あるタイプを予期していて別のタイプが返されたことを意味します。認識されないメンバーは、メンバーが認識されなかったことを意味します。

0