書くことが有効であることを考えると
a = b = c = 2;
それよりもいいでしょう
bool allTwo = a == 2 && b == 2 && c == 2;
代わりに書く
bool allTwo = a == b == c == 2;
しかし、a == bはブール値に評価され、整数と比較できないため、私はできません。
このように実装された言語設計の理由はありますか?
書くことが有効であることを考えると
a = b = c = 2;
それよりもいいでしょう
bool allTwo = a == 2 && b == 2 && c == 2;
代わりに書く
bool allTwo = a == b == c == 2;
しかし、a == bはブール値に評価され、整数と比較できないため、私はできません。
このように実装された言語設計の理由はありますか?
式の型a == b
はブール値であるため、式がそのコンテキストに関係なく同じことを意味するというルールを破るか、 n-ary == 演算子を使用して、ではなくa == b == c
として解析する必要があります。つまり、ブール値 c を の結果と比較する必要があります。これは問題ありませんが、C# の伝統である単純な C スタイルの文法ではありません。(== a b c)
(== (== a b) c)
(a == b) == c
(a == b)
式c == 2
は を返すtrue
ので、2 ではなくb
と比較されます。true
編集:Cスタイルの言語がブール式を処理する方法であるため、この方法で実装された可能性が最も高いです。複数の用語に対して特別な例外を作成し、別の方法で実装する必要がありますが、代入演算子の場合はより簡単です。最も右側の式は、チェーン内の次の式に論理的に適用できる値に評価されます。デザイナーはシンプルなアプローチをとったようです。
私の観点からは、それは明確さの問題です。決定が私次第だったとしたら、そのような言語機能を追加すると、複雑な式の評価方法に関してあいまいさが増しすぎる可能性があると思います。特定の状況では、a == b == cは(a == b)== cとは異なりますか?cをbと比較するのではなく、cをa == bのブール結果と本当に比較したい場合はどうなりますか?ほとんどの場合、コンパイラーはおそらく適切な比較を理解できますが、cが暗黙的にboolに変換可能である場合、可能性は低いですが、判断できない可能性があります。
個人的には、面倒な価値があるかどうかはわかりません。構文的には見栄えがよくないかもしれませんが、以下のように、複数のオブジェクトの同等性を比較するための独自のユーティリティ関数を作成できます。
public static bool Equals(this object x, params object[] y)
{
for (int i = 0; i < y.Length; i++)
{
if (!object.Equals(x, y[i]))
return false;
}
return true;
}
次に、次のように使用できます。
if (a.Equals(b, c, d, e, f, g))
{
// ...
}
引用を見つけることができませんが、Eric Lippert (?) が最もよく言ったと思います: 機能を実装しないことは無料です。http://blog.ryjones.org/2005/07/12/product-development/およびhttp://blog.ryjones.org/2005/07/12/product-development/も参照してください。
実装する機能はたくさんありますが、このような非標準で価値が疑わしいものが優先されるとは思えません。価値がないと言っているわけではありませんが、混乱を招く可能性があり、おそらくあまり使用されないでしょう.a1ex07にも良い点があると思います. これはもはや一般的に処理できないため、カスタムケースでなければなりません (== 常にブール値を返すなど)。
LINQ でも同じことができるようになりましたが、構文が少し複雑になり、何らかの配列を割り当てる必要があります。
bool allTwo = new int[] { a, b, c }.All(i => i == 2);
逆方向に実行して、!= 2 があるかどうかを確認できます。
bool allNotTwo = new int[] { a, b, c }.Any(i => i != 2);
どちらの場合も、一方が無効になるとすぐに終了するため、リスト全体を調べないことがよくあります。
編集: ここでもう 1 つポイントがあります: C# には多すぎる言語機能がありますか?
何か新しいことは、それを言語にするのに非常に役立つ
戻り値を無視すると、演算子の結合性とも関係があります。
代入演算子は右結合です。つまり、代入演算子の右側が最初に評価されます。a = b = c = 2
これが、実行してすべてに値2を割り当てることができる理由です。そうしないa
と、の古い値との古い値をb
持つb
ことになりますc
。
他のほとんどの演算子、特に短絡論理演算子(&&
および||
)は左結合です。つまり、a == b
または最初にa && b
評価します。a
.NETでは、オブジェクトの場合、 (オーバーライドされない限り)変換されない(または、それは...私は決して覚えていない==
)ため、それができないことを除いて、それは正しい連想である可能性があると主張できます。a == b
a.Equals(b)
a.ReferenceEquals(b)
やりたいことをするために、operator ==
オブジェクトを返す必要があります。この場合、別の問題が発生します。オブジェクトをブール値に暗黙的に変換する必要があります。このような変換は、追加の問題も引き起こします。
あなたの質問は、あなたの基準でいくらか悪化していると思います。
あなたが望んでいるように動作a = b = c = 2
するはずだと示唆する魔法は何もありません- 実際にはもっと - 反対です。a == b == c == 2
代入演算子は 2 つのオペランドに対してのみ定義され、設定されている値を返します。それらの文字列は、各演算子から次の演算子に値を渡すだけです。
1: a = (b = (c = 2));
2: a = (b = (2));
3: a = (2);
したがって、同じことが次の場合にも当てはまりますa == b == c == 2
。
1: bool allTwo = (a == (b == (c == 2)));
2: bool allTwo = (a == (b == ([Boolean])));
3: bool allTwo = (a == ([Boolean]));
4: bool allTwo = ([Boolean]);
したがって、技術的な理由は単純C#
に、一連の演算子を特別に処理するための定義が含まれていないことです。
言語の設計と実装に関しては、その理由はおそらくあいまいさと追加の複雑さを防ぐためです。今はすべて等しいa == b == c == 2
演算子として定義したいかもしれませんが、次の行では、現在実装されているように振る舞う必要があるかもしれません。行動はどのように区別されるべきですか?そして、実装する努力をするだけの価値があるでしょうか?
それともa == 2 && b == 2
本当に悪いことですか?;)
あなたの質問に対する直接的な回答ではありませんが、以下はどうでしょうか。
bool allTwo = a & b & c == 2;
編集: ピートが言うように、それはうまくいきません。どうですか?
bool allEqual(params int[] inputs)
{
int lastval = inputs[0];
for (int i = 1; i < inputs.length; i++)
{
if (lastval != inputs[i])
return false;
lastval = inputs[i];
}
return true;
}
一度宣言すれば、比較する整数のコンマ区切りリストをいつでも使用できます。(おそらくもっと単純な関数がありますが、何でも構いません。)
bool allTwo = a == b && b == c && c == 2; // prefer this format over a == 2 && b == 2 && c == 2, personally
対
bool allTwo = allEqual(a, b, c, 2);
あなたの質問自体に関して、他の人の回答でまだ言われていないことについて、私が言うことはあまりありません。