Eric Lippertが彼の回答で述べた特定のポイントについて詳しく説明し、他の誰にもまったく触れられていない特定の機会にスポットライトを当てたいと思います。エリックは言った:
[...]割り当ては、ほとんどの場合、レジスタに割り当てられたばかりの値を残します。
割り当ては常に、左側のオペランドに割り当てようとした値を残します。「ほぼ常に」ではない。しかし、ドキュメントでコメントされているこの問題を見つけられなかったので、私にはわかりません。理論的には、「残して」左のオペランドを再評価しない非常に効果的な実装手順ですが、効率的ですか?
これまでのところ、このスレッドの回答で構築されたすべての例で「効率的」です。しかし、getおよびsetアクセサーを使用するプロパティとインデクサーの場合は効率的ですか?どういたしまして。このコードを考えてみましょう:
class Test
{
public bool MyProperty { get { return true; } set { ; } }
}
ここには、プライベート変数のラッパーではないプロパティがあります。彼が呼ばれるときはいつでも彼は真を返すでしょう、彼が値を設定しようとするときはいつでも彼は何もしません。したがって、この特性が評価されるときはいつでも、彼は真実であろう。しばらく様子を見てみましょう:
Test test = new Test();
if ((test.MyProperty = false) == true)
Console.WriteLine("Please print this text.");
else
Console.WriteLine("Unexpected!!");
それが印刷するものを推測しますか?印刷しUnexpected!!ます。結局のところ、setアクセサは実際に呼び出され、何も実行しません。しかし、その後、getアクセサーはまったく呼び出されません。false割り当ては、プロパティに割り当てようとした値を残すだけです。そして、このfalse値はifステートメントが評価するものです。
最後に、この問題を調査させた実際の例を挙げます。私のList<string>クラスがプライベート変数として持っているコレクション()の便利なラッパーであるインデクサーを作成しました。
インデクサーに送信されたパラメーターは文字列でした。これは、私のコレクションの値として扱われます。getアクセサーは、その値がリストに存在するかどうかにかかわらず、単にtrueまたはfalseを返します。したがって、getアクセサーは、List<T>.Containsメソッドを使用する別の方法でした。
文字列を引数としてインデクサーのセットアクセサーが呼び出され、右側のオペランドがboolであるtrue場合、そのパラメーターをリストに追加します。ただし、同じパラメーターがアクセサーに送信され、正しいオペランドがboolのfalse場合、代わりにリストから要素が削除されます。したがって、セットアクセサは、List<T>.Addおよびの両方の便利な代替手段として使用されましたList<T>.Remove。
自分のロジックをゲートウェイとして実装してリストをラップする、きちんとしたコンパクトな「API」があると思いました。インデクサーの助けを借りて、私はいくつかのキーストロークのセットで多くのことを行うことができました。たとえば、リストに値を追加して、そこにあることを確認するにはどうすればよいですか?私はこれが必要な唯一のコード行だと思いました:
if (myObject["stringValue"] = true)
; // Set operation succeeded..!
しかし、前の例で示したように、値が本当にリストにあるかどうかを確認するはずのgetアクセサーは呼び出されていません。true値は常に背後に効果的に私は私のgetアクセサに実装されていたものは何でも、論理破壊残っていました。