等値演算子 - 2 つのオブジェクトが等しいかどうかをテストします
==
(等価) と !=
(非等値) 演算子は、そのオペランドが等しいかどうを確認します。 内容が等しい場合、値の型は等しくなります。 2 つの変数が同じストレージを参照している場合、参照型は等しくなります。
等値演算子 ==
等値演算子 ==
は、そのオペランドが等しい場合には true
を返し、それ以外の場合は false
を返します。
値の型の等価性
組み込みの値の型のオペランドは、その値が等しい場合は等しくなります。
int a = 1 + 2 + 3;
int b = 6;
Console.WriteLine(a == b); // output: True
char c1 = 'a';
char c2 = 'A';
Console.WriteLine(c1 == c2); // output: False
Console.WriteLine(c1 == char.ToLower(c2)); // output: True
注意
==
、<
、>
、<=
、および >=
演算子の場合、いずれかのオペランドが数値 (Double.NaN または Single.NaN) でない場合、演算結果は false
になります。 つまり、NaN
の値は、NaN
を含む他のどの double
(または float
) の値を上回ることも、下回ることも、等しいこともありません。 詳細およびサンプルについては、Double.NaN または Single.NaN の参照記事をご覧ください。
同じ列挙型の 2 つのオペランドは、基になる整数型の対応する値が等しい場合は等しくなります。
既定ではユーザー定義 struct 型は ==
演算子をサポートしていません。 ==
演算子をサポートするには、ユーザー定義 struct でそれをオーバーロードする必要があります。
==
および !=
演算子は、C# のタプルによってサポートされています。 詳細については、タプル型に関する記事のタプルの等価性に関するセクションを参照してください。
参照型の等価性
既定では、レコードではない 2 つの参照型オペランドは、同じオブジェクトを参照しているときに等しくなります。
public class ReferenceTypesEquality
{
public class MyClass
{
private int id;
public MyClass(int id) => this.id = id;
}
public static void Main()
{
var a = new MyClass(1);
var b = new MyClass(1);
var c = a;
Console.WriteLine(a == b); // output: False
Console.WriteLine(a == c); // output: True
}
}
次の例は、ユーザー定義の参照型が既定で ==
演算子をサポートしていることを示しています。 ただし、参照型は ==
演算子をオーバーロードできます。 参照型が ==
演算子をオーバーロードする場合、その型の 2 つの参照が同じオブジェクトを参照しているかどうかを調べるには Object.ReferenceEquals メソッドを使用します。
レコードの型の等価性
レコード型では、既定で値の等価性セマンティクスを提供する ==
演算子と !=
演算子がサポートされています。 つまり、両方がすべてのフィールドの null
または対応する値であり、自動的に実装されるプロパティが等しい場合、2 つのレコード オペランドが等しくなります。
public class RecordTypesEquality
{
public record Point(int X, int Y, string Name);
public record TaggedNumber(int Number, List<string> Tags);
public static void Main()
{
var p1 = new Point(2, 3, "A");
var p2 = new Point(1, 3, "B");
var p3 = new Point(2, 3, "A");
Console.WriteLine(p1 == p2); // output: False
Console.WriteLine(p1 == p3); // output: True
var n1 = new TaggedNumber(2, new List<string>() { "A" });
var n2 = new TaggedNumber(2, new List<string>() { "A" });
Console.WriteLine(n1 == n2); // output: False
}
}
前の例からわかるように、レコードではない参照型メンバーの場合、参照されるインスタンスではなく、参照値が比較されます。
文字列の等価性
2 つの string オペランドは、その両方が null
であるか、両方の文字列インスタンスの長さが同じで、それぞれの文字列の位置に同じ文字が含まれている場合に等しくなります。
string s1 = "hello!";
string s2 = "HeLLo!";
Console.WriteLine(s1 == s2.ToLower()); // output: True
string s3 = "Hello!";
Console.WriteLine(s1 == s3); // output: False
文字列の等価比較は、大文字と小文字が区別される序数比較です。 文字列の比較に関する詳細については、「C# で文字列を比較する方法」を参照してください。
デリゲートの等価性
同じランタイム型を持つ 2 つのデリゲート オペランドが等しくなるのは、それらの両方が null
であるか、それらの呼び出しリストが同じ長さで、各位置に等しいエントリを含んでいる場合です。
Action a = () => Console.WriteLine("a");
Action b = a + a;
Action c = a + a;
Console.WriteLine(object.ReferenceEquals(b, c)); // output: False
Console.WriteLine(b == c); // output: True
詳細については、C# 言語仕様の「Delegate equality operators (デリゲートの等値演算子)」セクションをご覧ください。
次の例に示すように、意味的に等しいラムダ式を評価して生成されるデリゲートは、等しくありません。
Action a = () => Console.WriteLine("a");
Action b = () => Console.WriteLine("a");
Console.WriteLine(a == b); // output: False
Console.WriteLine(a + b == a + b); // output: True
Console.WriteLine(b + a == a + b); // output: False
非等値演算子 !=
非等値演算子 !=
は、そのオペランドが等しくない場合には true
を返し、それ以外の場合は false
を返します。 組み込み型のオペランドの場合、式 x != y
と式 !(x == y)
では同じ結果が生成されます。 等価型の詳細については、「等値演算子」セクションを参照してください。
!=
演算子の使用例を次に示します。
int a = 1 + 1 + 2 + 3;
int b = 6;
Console.WriteLine(a != b); // output: True
string s1 = "Hello";
string s2 = "Hello";
Console.WriteLine(s1 != s2); // output: False
object o1 = 1;
object o2 = 1;
Console.WriteLine(o1 != o2); // output: True
演算子のオーバーロード可/不可
ユーザー定義型は ==
演算子と !=
演算子をオーバーロードできます。 ある型でこの 2 つの演算子の 1 つをオーバーロードする場合は、もう 1 つの演算子もオーバーロードする必要があります。
レコードの型で ==
演算子と !=
演算子を明示的にオーバーロードすることはできません。 レコードの型 T
の ==
演算子と !=
演算子の動作を変更する必要がある場合、次のシグネチャで IEquatable<T>.Equals メソッドを実装します。
public virtual bool Equals(T? other);
C# 言語仕様
詳細については、C# 言語仕様に関するページの「関係演算子と型検査演算子」のセクションを参照してください。
レコードの型の等価性に関する詳細については、レコード機能提案メモ ページの「等値メンバー」セクションを参照してください。
関連項目
.NET