Object.Equals Metoda
Definice
Důležité
Některé informace platí pro předběžně vydaný produkt, který se může zásadně změnit, než ho výrobce nebo autor vydá. Microsoft neposkytuje žádné záruky, výslovné ani předpokládané, týkající se zde uváděných informací.
Určuje, zda jsou obě instance objektu stejné.
Přetížení
Equals(Object) |
Určí, zda se zadaný objekt rovná aktuálnímu objektu. |
Equals(Object, Object) |
Určuje, zda jsou zadané instance objektů považovány za stejné. |
Equals(Object)
Určí, zda se zadaný objekt rovná aktuálnímu objektu.
public:
virtual bool Equals(System::Object ^ obj);
public virtual bool Equals (object obj);
public virtual bool Equals (object? obj);
abstract member Equals : obj -> bool
override this.Equals : obj -> bool
Public Overridable Function Equals (obj As Object) As Boolean
Parametry
- obj
- Object
Objekt, který má být porovnán s aktuálním objektem
Návraty
true
je-li zadaný objekt roven aktuálnímu objektu; v opačném případě . false
Příklady
Následující příklad ukazuje Point
třídu, která přepíše metodu Equals tak, aby poskytovala rovnost hodnot, a Point3D
třídu, která je odvozena od Point
. Vzhledem k tomu Point
, že přepsání Object.Equals(Object) pro testování rovnosti hodnot, Object.Equals(Object) není volána metoda. VoláníPoint.Equals
, Point3D.Equals
protože Point
implementuje Object.Equals(Object) způsobem, který poskytuje rovnost hodnot.
using System;
class Point
{
protected int x, y;
public Point() : this(0, 0)
{ }
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
public override bool Equals(Object obj)
{
//Check for null and compare run-time types.
if ((obj == null) || ! this.GetType().Equals(obj.GetType()))
{
return false;
}
else {
Point p = (Point) obj;
return (x == p.x) && (y == p.y);
}
}
public override int GetHashCode()
{
return (x << 2) ^ y;
}
public override string ToString()
{
return String.Format("Point({0}, {1})", x, y);
}
}
sealed class Point3D: Point
{
int z;
public Point3D(int x, int y, int z) : base(x, y)
{
this.z = z;
}
public override bool Equals(Object obj)
{
Point3D pt3 = obj as Point3D;
if (pt3 == null)
return false;
else
return base.Equals((Point)obj) && z == pt3.z;
}
public override int GetHashCode()
{
return (base.GetHashCode() << 2) ^ z;
}
public override String ToString()
{
return String.Format("Point({0}, {1}, {2})", x, y, z);
}
}
class Example
{
public static void Main()
{
Point point2D = new Point(5, 5);
Point3D point3Da = new Point3D(5, 5, 2);
Point3D point3Db = new Point3D(5, 5, 2);
Point3D point3Dc = new Point3D(5, 5, -1);
Console.WriteLine("{0} = {1}: {2}",
point2D, point3Da, point2D.Equals(point3Da));
Console.WriteLine("{0} = {1}: {2}",
point2D, point3Db, point2D.Equals(point3Db));
Console.WriteLine("{0} = {1}: {2}",
point3Da, point3Db, point3Da.Equals(point3Db));
Console.WriteLine("{0} = {1}: {2}",
point3Da, point3Dc, point3Da.Equals(point3Dc));
}
}
// The example displays the following output:
// Point(5, 5) = Point(5, 5, 2): False
// Point(5, 5) = Point(5, 5, 2): False
// Point(5, 5, 2) = Point(5, 5, 2): True
// Point(5, 5, 2) = Point(5, 5, -1): False
type Point(x, y) =
new () = Point(0, 0)
member _.X = x
member _.Y = y
override _.Equals(obj) =
//Check for null and compare run-time types.
match obj with
| :? Point as p ->
x = p.X && y = p.Y
| _ ->
false
override _.GetHashCode() =
(x <<< 2) ^^^ y
override _.ToString() =
$"Point({x}, {y})"
type Point3D(x, y, z) =
inherit Point(x, y)
member _.Z = z
override _.Equals(obj) =
match obj with
| :? Point3D as pt3 ->
base.Equals(pt3 :> Point) && z = pt3.Z
| _ ->
false
override _.GetHashCode() =
(base.GetHashCode() <<< 2) ^^^ z
override _.ToString() =
$"Point({x}, {y}, {z})"
let point2D = Point(5, 5)
let point3Da = Point3D(5, 5, 2)
let point3Db = Point3D(5, 5, 2)
let point3Dc = Point3D(5, 5, -1)
printfn $"{point2D} = {point3Da}: {point2D.Equals point3Da}"
printfn $"{point2D} = {point3Db}: {point2D.Equals point3Db}"
printfn $"{point3Da} = {point3Db}: {point3Da.Equals point3Db}"
printfn $"{point3Da} = {point3Dc}: {point3Da.Equals point3Dc}"
// The example displays the following output:
// Point(5, 5) = Point(5, 5, 2): False
// Point(5, 5) = Point(5, 5, 2): False
// Point(5, 5, 2) = Point(5, 5, 2): True
// Point(5, 5, 2) = Point(5, 5, -1): False
Class Point
Protected x, y As Integer
Public Sub New()
Me.x = 0
Me.y = 0
End Sub
Public Sub New(x As Integer, y As Integer)
Me.x = x
Me.y = y
End Sub
Public Overrides Function Equals(obj As Object) As Boolean
' Check for null and compare run-time types.
If obj Is Nothing OrElse Not Me.GetType().Equals(obj.GetType()) Then
Return False
Else
Dim p As Point = DirectCast(obj, Point)
Return x = p.x AndAlso y = p.y
End If
End Function
Public Overrides Function GetHashCode() As Integer
Return (x << 2) XOr y
End Function
Public Overrides Function ToString() As String
Return String.Format("Point({0}, {1})", x, y)
End Function
End Class
Class Point3D : Inherits Point
Private z As Integer
Public Sub New(ByVal x As Integer, ByVal y As Integer, ByVal z As Integer)
MyBase.New(x, y)
Me.z = Z
End Sub
Public Overrides Function Equals(ByVal obj As Object) As Boolean
Dim pt3 As Point3D = TryCast(obj, Point3D)
If pt3 Is Nothing Then
Return False
Else
Return MyBase.Equals(CType(pt3, Point)) AndAlso z = pt3.Z
End If
End Function
Public Overrides Function GetHashCode() As Integer
Return (MyBase.GetHashCode() << 2) XOr z
End Function
Public Overrides Function ToString() As String
Return String.Format("Point({0}, {1}, {2})", x, y, z)
End Function
End Class
Module Example
Public Sub Main()
Dim point2D As New Point(5, 5)
Dim point3Da As New Point3D(5, 5, 2)
Dim point3Db As New Point3D(5, 5, 2)
Dim point3Dc As New Point3D(5, 5, -1)
Console.WriteLine("{0} = {1}: {2}",
point2D, point3Da, point2D.Equals(point3Da))
Console.WriteLine("{0} = {1}: {2}",
point2D, point3Db, point2D.Equals(point3Db))
Console.WriteLine("{0} = {1}: {2}",
point3Da, point3Db, point3Da.Equals(point3Db))
Console.WriteLine("{0} = {1}: {2}",
point3Da, point3Dc, point3Da.Equals(point3Dc))
End Sub
End Module
' The example displays the following output
' Point(5, 5) = Point(5, 5, 2): False
' Point(5, 5) = Point(5, 5, 2): False
' Point(5, 5, 2) = Point(5, 5, 2): True
' Point(5, 5, 2) = Point(5, 5, -1): False
Metoda Point.Equals
zkontroluje, zda obj
argument není null a že odkazuje na instanci stejného typu jako tento objekt. Pokud se některé z kontrol nezdaří, metoda vrátí false
.
Metoda Point.Equals
volá metodu GetType k určení, zda jsou typy za běhu těchto dvou objektů identické. Pokud metoda použila kontrolu formuláře obj is Point
v jazyce C# nebo TryCast(obj, Point)
v Visual Basic, vrátí se kontrola true
v případech, kdy obj
je instance odvozené třídy Point
, i když obj
a aktuální instance nejsou stejného typu běhu. Po ověření, že oba objekty jsou stejného typu, metoda přetypuje obj
na typ Point
a vrátí výsledek porovnání polí instance obou objektů.
V Point3D.Equals
, zděděná Point.Equals
metoda, která přepíše Object.Equals(Object), je vyvolána před cokoli jiného je provedeno. Protože Point3D
je zapečetěná třída (NotInheritable
v Visual Basic), je kontrola ve formuláři obj is Point
v jazyce C# nebo TryCast(obj, Point)
v Visual Basic vhodná k zajištění, že obj
je Point3D
to objekt. Pokud se jedná o Point3D
objekt, přetypuje se na Point
objekt a předá se implementaci Equalszákladní třídy . Pouze když zděděná Point.Equals
metoda vrátí true
, porovná metoda z
pole instance zavedená v odvozené třídě.
Následující příklad definuje Rectangle
třídu, která interně implementuje obdélník jako dva Point
objekty. Třída Rectangle
také přepíše Object.Equals(Object) , aby poskytovala rovnost hodnot.
using System;
class Rectangle
{
private Point a, b;
public Rectangle(int upLeftX, int upLeftY, int downRightX, int downRightY)
{
this.a = new Point(upLeftX, upLeftY);
this.b = new Point(downRightX, downRightY);
}
public override bool Equals(Object obj)
{
// Perform an equality check on two rectangles (Point object pairs).
if (obj == null || GetType() != obj.GetType())
return false;
Rectangle r = (Rectangle)obj;
return a.Equals(r.a) && b.Equals(r.b);
}
public override int GetHashCode()
{
return Tuple.Create(a, b).GetHashCode();
}
public override String ToString()
{
return String.Format("Rectangle({0}, {1}, {2}, {3})",
a.x, a.y, b.x, b.y);
}
}
class Point
{
internal int x;
internal int y;
public Point(int X, int Y)
{
this.x = X;
this.y = Y;
}
public override bool Equals (Object obj)
{
// Performs an equality check on two points (integer pairs).
if (obj == null || GetType() != obj.GetType()) return false;
Point p = (Point)obj;
return (x == p.x) && (y == p.y);
}
public override int GetHashCode()
{
return Tuple.Create(x, y).GetHashCode();
}
}
class Example
{
public static void Main()
{
Rectangle r1 = new Rectangle(0, 0, 100, 200);
Rectangle r2 = new Rectangle(0, 0, 100, 200);
Rectangle r3 = new Rectangle(0, 0, 150, 200);
Console.WriteLine("{0} = {1}: {2}", r1, r2, r1.Equals(r2));
Console.WriteLine("{0} = {1}: {2}", r1, r3, r1.Equals(r3));
Console.WriteLine("{0} = {1}: {2}", r2, r3, r2.Equals(r3));
}
}
// The example displays the following output:
// Rectangle(0, 0, 100, 200) = Rectangle(0, 0, 100, 200): True
// Rectangle(0, 0, 100, 200) = Rectangle(0, 0, 150, 200): False
// Rectangle(0, 0, 100, 200) = Rectangle(0, 0, 150, 200): False
type Point(x, y) =
member _.X = x
member _.Y = y
override _.Equals(obj) =
// Performs an equality check on two points (integer pairs).
match obj with
| :? Point as p ->
x = p.X && y = p.Y
| _ ->
false
override _.GetHashCode() =
(x, y).GetHashCode()
type Rectangle(upLeftX, upLeftY, downRightX, downRightY) =
let a = Point(upLeftX, upLeftY)
let b = Point(downRightX, downRightY)
member _.UpLeft = a
member _.DownRight = b
override _.Equals(obj) =
// Perform an equality check on two rectangles (Point object pairs).
match obj with
| :? Rectangle as r ->
a.Equals(r.UpLeft) && b.Equals(r.DownRight)
| _ ->
false
override _.GetHashCode() =
(a, b).GetHashCode()
override _.ToString() =
$"Rectangle({a.X}, {a.Y}, {b.X}, {b.Y})"
let r1 = Rectangle(0, 0, 100, 200)
let r2 = Rectangle(0, 0, 100, 200)
let r3 = Rectangle(0, 0, 150, 200)
printfn $"{r1} = {r2}: {r1.Equals r2}"
printfn $"{r1} = {r3}: {r1.Equals r3}"
printfn $"{r2} = {r3}: {r2.Equals r3}"
// The example displays the following output:
// Rectangle(0, 0, 100, 200) = Rectangle(0, 0, 100, 200): True
// Rectangle(0, 0, 100, 200) = Rectangle(0, 0, 150, 200): False
// Rectangle(0, 0, 100, 200) = Rectangle(0, 0, 150, 200): False
Class Rectangle
Private a, b As Point
Public Sub New(ByVal upLeftX As Integer, ByVal upLeftY As Integer, _
ByVal downRightX As Integer, ByVal downRightY As Integer)
Me.a = New Point(upLeftX, upLeftY)
Me.b = New Point(downRightX, downRightY)
End Sub
Public Overrides Function Equals(ByVal obj As [Object]) As Boolean
' Performs an equality check on two rectangles (Point object pairs).
If obj Is Nothing OrElse Not [GetType]().Equals(obj.GetType()) Then
Return False
End If
Dim r As Rectangle = CType(obj, Rectangle)
Return a.Equals(r.a) AndAlso b.Equals(r.b)
End Function
Public Overrides Function GetHashCode() As Integer
Return Tuple.Create(a, b).GetHashCode()
End Function
Public Overrides Function ToString() As String
Return String.Format("Rectangle({0}, {1}, {2}, {3})",
a.x, a.y, b.x, b.y)
End Function
End Class
Class Point
Friend x As Integer
Friend y As Integer
Public Sub New(ByVal X As Integer, ByVal Y As Integer)
Me.x = X
Me.y = Y
End Sub
Public Overrides Function Equals(ByVal obj As [Object]) As Boolean
' Performs an equality check on two points (integer pairs).
If obj Is Nothing OrElse Not [GetType]().Equals(obj.GetType()) Then
Return False
Else
Dim p As Point = CType(obj, Point)
Return x = p.x AndAlso y = p.y
End If
End Function
Public Overrides Function GetHashCode() As Integer
Return Tuple.Create(x, y).GetHashCode()
End Function
End Class
Class Example
Public Shared Sub Main()
Dim r1 As New Rectangle(0, 0, 100, 200)
Dim r2 As New Rectangle(0, 0, 100, 200)
Dim r3 As New Rectangle(0, 0, 150, 200)
Console.WriteLine("{0} = {1}: {2}", r1, r2, r1.Equals(r2))
Console.WriteLine("{0} = {1}: {2}", r1, r3, r1.Equals(r3))
Console.WriteLine("{0} = {1}: {2}", r2, r3, r2.Equals(r3))
End Sub
End Class
' The example displays the following output:
' Rectangle(0, 0, 100, 200) = Rectangle(0, 0, 100, 200): True
' Rectangle(0, 0, 100, 200) = Rectangle(0, 0, 150, 200): False
' Rectangle(0, 0, 100, 200) = Rectangle(0, 0, 150, 200): False
Některé jazyky, jako je C# a Visual Basic, podporují přetížení operátoru. Když typ přetěžuje operátor rovnosti, musí také přepsat metodu Equals(Object) , aby poskytovala stejné funkce. Toho se obvykle dosahuje zápisem Equals(Object) metody z hlediska přetíženého operátoru rovnosti, jako v následujícím příkladu.
using System;
public struct Complex
{
public double re, im;
public override bool Equals(Object obj)
{
return obj is Complex && this == (Complex)obj;
}
public override int GetHashCode()
{
return Tuple.Create(re, im).GetHashCode();
}
public static bool operator ==(Complex x, Complex y)
{
return x.re == y.re && x.im == y.im;
}
public static bool operator !=(Complex x, Complex y)
{
return !(x == y);
}
public override String ToString()
{
return String.Format("({0}, {1})", re, im);
}
}
class MyClass
{
public static void Main()
{
Complex cmplx1, cmplx2;
cmplx1.re = 4.0;
cmplx1.im = 1.0;
cmplx2.re = 2.0;
cmplx2.im = 1.0;
Console.WriteLine("{0} <> {1}: {2}", cmplx1, cmplx2, cmplx1 != cmplx2);
Console.WriteLine("{0} = {1}: {2}", cmplx1, cmplx2, cmplx1.Equals(cmplx2));
cmplx2.re = 4.0;
Console.WriteLine("{0} = {1}: {2}", cmplx1, cmplx2, cmplx1 == cmplx2);
Console.WriteLine("{0} = {1}: {2}", cmplx1, cmplx2, cmplx1.Equals(cmplx2));
}
}
// The example displays the following output:
// (4, 1) <> (2, 1): True
// (4, 1) = (2, 1): False
// (4, 1) = (4, 1): True
// (4, 1) = (4, 1): True
[<Struct; CustomEquality; NoComparison>]
type Complex =
val mutable re: double
val mutable im: double
override this.Equals(obj) =
match obj with
| :? Complex as c when c = this -> true
| _ -> false
override this.GetHashCode() =
(this.re, this.im).GetHashCode()
override this.ToString() =
$"({this.re}, {this.im})"
static member op_Equality (x: Complex, y: Complex) =
x.re = y.re && x.im = y.im
static member op_Inequality (x: Complex, y: Complex) =
x = y |> not
let mutable cmplx1 = Complex()
let mutable cmplx2 = Complex()
cmplx1.re <- 4.0
cmplx1.im <- 1.0
cmplx2.re <- 2.0
cmplx2.im <- 1.0
printfn $"{cmplx1} <> {cmplx2}: {cmplx1 <> cmplx2}"
printfn $"{cmplx1} = {cmplx2}: {cmplx1.Equals cmplx2}"
cmplx2.re <- 4.0
printfn $"{cmplx1} = {cmplx2}: {cmplx1 = cmplx2}"
printfn $"{cmplx1} = {cmplx2}: {cmplx1.Equals cmplx2}"
// The example displays the following output:
// (4, 1) <> (2, 1): True
// (4, 1) = (2, 1): False
// (4, 1) = (4, 1): True
// (4, 1) = (4, 1): True
Public Structure Complex
Public re, im As Double
Public Overrides Function Equals(ByVal obj As [Object]) As Boolean
Return TypeOf obj Is Complex AndAlso Me = CType(obj, Complex)
End Function
Public Overrides Function GetHashCode() As Integer
Return Tuple.Create(re, im).GetHashCode()
End Function
Public Shared Operator = (x As Complex, y As Complex) As Boolean
Return x.re = y.re AndAlso x.im = y.im
End Operator
Public Shared Operator <> (x As Complex, y As Complex) As Boolean
Return Not (x = y)
End Operator
Public Overrides Function ToString() As String
Return String.Format("({0}, {1})", re, im)
End Function
End Structure
Class Example
Public Shared Sub Main()
Dim cmplx1, cmplx2 As Complex
cmplx1.re = 4.0
cmplx1.im = 1.0
cmplx2.re = 2.0
cmplx2.im = 1.0
Console.WriteLine("{0} <> {1}: {2}", cmplx1, cmplx2, cmplx1 <> cmplx2)
Console.WriteLine("{0} = {1}: {2}", cmplx1, cmplx2, cmplx1.Equals(cmplx2))
cmplx2.re = 4.0
Console.WriteLine("{0} = {1}: {2}", cmplx1, cmplx2, cmplx1 = cmplx2)
Console.WriteLine("{0} = {1}: {2}", cmplx1, cmplx2, cmplx1.Equals(cmplx2))
End Sub
End Class
' The example displays the following output:
' (4, 1) <> (2, 1): True
' (4, 1) = (2, 1): False
' (4, 1) = (4, 1): True
' (4, 1) = (4, 1): True
Vzhledem k tomu, že Complex
je typ hodnoty, nelze jej odvodit. Proto přepsání metody Equals(Object) nemusí volat GetType k určení přesného typu běhu každého objektu, ale může místo toho použít is
operátor v jazyce C# nebo TypeOf
operátor v Visual Basic ke kontrole typu parametruobj
.
Poznámky
Typ porovnání mezi aktuální instancí a obj
parametrem závisí na tom, jestli je aktuální instance referenčním typem nebo typem hodnoty.
Pokud je aktuální instance referenčním typem, Equals(Object) testuje metodu rovnosti odkazů a volání Equals(Object) metody je ekvivalentní volání metody ReferenceEquals . Rovnost odkazů znamená, že proměnné objektu, které se porovnávají, odkazují na stejný objekt. Následující příklad znázorňuje výsledek takového porovnání. Definuje
Person
třídu, což je typ odkazu, a voláPerson
konstruktor třídy k vytvoření instance dvou novýchPerson
objektů aperson1a
person2
, které mají stejnou hodnotu. Přiřadí se taképerson1a
k jiné proměnné objektuperson1b
. Jak ukazuje výstup z příkladu aperson1b
jsou stejné,person1a
protože odkazují na stejný objekt.person1a
person2
Nejsou však stejné, i když mají stejnou hodnotu.using System; // Define a reference type that does not override Equals. public class Person { private string personName; public Person(string name) { this.personName = name; } public override string ToString() { return this.personName; } } public class Example { public static void Main() { Person person1a = new Person("John"); Person person1b = person1a; Person person2 = new Person(person1a.ToString()); Console.WriteLine("Calling Equals:"); Console.WriteLine("person1a and person1b: {0}", person1a.Equals(person1b)); Console.WriteLine("person1a and person2: {0}", person1a.Equals(person2)); Console.WriteLine("\nCasting to an Object and calling Equals:"); Console.WriteLine("person1a and person1b: {0}", ((object) person1a).Equals((object) person1b)); Console.WriteLine("person1a and person2: {0}", ((object) person1a).Equals((object) person2)); } } // The example displays the following output: // person1a and person1b: True // person1a and person2: False // // Casting to an Object and calling Equals: // person1a and person1b: True // person1a and person2: False
// Define a reference type that does not override Equals. type Person(name) = override _.ToString() = name let person1a = Person "John" let person1b = person1a let person2 = Person(string person1a) printfn "Calling Equals:" printfn $"person1a and person1b: {person1a.Equals person1b}" printfn $"person1a and person2: {person1a.Equals person2}" printfn "\nCasting to an Object and calling Equals:" printfn $"person1a and person1b: {(person1a :> obj).Equals(person1b :> obj)}" printfn $"person1a and person2: {(person1a :> obj).Equals(person2 :> obj)}" // The example displays the following output: // person1a and person1b: True // person1a and person2: False // // Casting to an Object and calling Equals: // person1a and person1b: True // person1a and person2: False
' Define a reference type that does not override Equals. Public Class Person Private personName As String Public Sub New(name As String) Me.personName = name End Sub Public Overrides Function ToString() As String Return Me.personName End Function End Class Module Example Public Sub Main() Dim person1a As New Person("John") Dim person1b As Person = person1a Dim person2 As New Person(person1a.ToString()) Console.WriteLine("Calling Equals:") Console.WriteLine("person1a and person1b: {0}", person1a.Equals(person1b)) Console.WriteLine("person1a and person2: {0}", person1a.Equals(person2)) Console.WriteLine() Console.WriteLine("Casting to an Object and calling Equals:") Console.WriteLine("person1a and person1b: {0}", CObj(person1a).Equals(CObj(person1b))) Console.WriteLine("person1a and person2: {0}", CObj(person1a).Equals(CObj(person2))) End Sub End Module ' The example displays the following output: ' Calling Equals: ' person1a and person1b: True ' person1a and person2: False ' ' Casting to an Object and calling Equals: ' person1a and person1b: True ' person1a and person2: False
Pokud je aktuální instance typ hodnoty, Equals(Object) metoda testuje rovnost hodnot. Rovnost hodnot znamená následující:
Dva objekty jsou stejného typu. Jak ukazuje následující příklad, Byte objekt, který má hodnotu 12, se nerovná Int32 objektu, který má hodnotu 12, protože oba objekty mají různé typy za běhu.
byte value1 = 12; int value2 = 12; object object1 = value1; object object2 = value2; Console.WriteLine("{0} ({1}) = {2} ({3}): {4}", object1, object1.GetType().Name, object2, object2.GetType().Name, object1.Equals(object2)); // The example displays the following output: // 12 (Byte) = 12 (Int32): False
let value1 = 12uy let value2 = 12 let object1 = value1 :> obj let object2 = value2 :> obj printfn $"{object1} ({object1.GetType().Name}) = {object2} ({object2.GetType().Name}): {object1.Equals object2}" // The example displays the following output: // 12 (Byte) = 12 (Int32): False
Module Example Public Sub Main() Dim value1 As Byte = 12 Dim value2 As Integer = 12 Dim object1 As Object = value1 Dim object2 As Object = value2 Console.WriteLine("{0} ({1}) = {2} ({3}): {4}", object1, object1.GetType().Name, object2, object2.GetType().Name, object1.Equals(object2)) End Sub End Module ' The example displays the following output: ' 12 (Byte) = 12 (Int32): False
Hodnoty veřejných a privátních polí těchto dvou objektů jsou stejné. Následující příklad testuje rovnost hodnot. Definuje
Person
strukturu, což je typ hodnoty, a voláPerson
konstruktor třídy k vytvoření instance dvou novýchPerson
objektů aperson1
person2
, které mají stejnou hodnotu. Jak ukazuje výstup z příkladu, i když dvě proměnné objektu odkazují na různé objekty aperson2
jsou stejné,person1
protože mají stejnou hodnotu pro privátnípersonName
pole.using System; // Define a value type that does not override Equals. public struct Person { private string personName; public Person(string name) { this.personName = name; } public override string ToString() { return this.personName; } } public struct Example { public static void Main() { Person person1 = new Person("John"); Person person2 = new Person("John"); Console.WriteLine("Calling Equals:"); Console.WriteLine(person1.Equals(person2)); Console.WriteLine("\nCasting to an Object and calling Equals:"); Console.WriteLine(((object) person1).Equals((object) person2)); } } // The example displays the following output: // Calling Equals: // True // // Casting to an Object and calling Equals: // True
// Define a value type that does not override Equals. [<Struct>] type Person(personName: string) = override _.ToString() = personName let person1 = Person "John" let person2 = Person "John" printfn "Calling Equals:" printfn $"{person1.Equals person2}" printfn $"\nCasting to an Object and calling Equals:" printfn $"{(person1 :> obj).Equals(person2 :> obj)}" // The example displays the following output: // Calling Equals: // True // // Casting to an Object and calling Equals: // True
' Define a value type that does not override Equals. Public Structure Person Private personName As String Public Sub New(name As String) Me.personName = name End Sub Public Overrides Function ToString() As String Return Me.personName End Function End Structure Module Example Public Sub Main() Dim p1 As New Person("John") Dim p2 As New Person("John") Console.WriteLine("Calling Equals:") Console.WriteLine(p1.Equals(p2)) Console.WriteLine() Console.WriteLine("Casting to an Object and calling Equals:") Console.WriteLine(CObj(p1).Equals(p2)) End Sub End Module ' The example displays the following output: ' Calling Equals: ' True ' ' Casting to an Object and calling Equals: ' True
Vzhledem k tomu, že Object třída je základní třída pro všechny typy v .NET Framework, Object.Equals(Object) metoda poskytuje výchozí porovnání rovnosti pro všechny ostatní typy. Typy ale často přepíší metodu Equals pro implementaci rovnosti hodnot. Další informace najdete v částech Poznámky pro volající a poznámky pro dědiče.
Poznámky pro prostředí Windows Runtime
Když zavoláte Equals(Object) přetížení metody třídy v prostředí Windows Runtime, poskytuje výchozí chování tříd, které nepřepíší Equals(Object). Tato podpora je součástí podpory, kterou .NET Framework poskytuje prostředí Windows Runtime (viz .NET Framework Podpora aplikací pro Windows Store a prostředí Windows Runtime). Třídy v prostředí Windows Runtime nedědí Objecta aktuálně neimplementují metoduEquals(Object). Zdá se ale, že mají ToString, Equals(Object)a GetHashCode metody, když je použijete v kódu C# nebo Visual Basic a .NET Framework poskytuje výchozí chování pro tyto metody.
Poznámka
prostředí Windows Runtime třídy napsané v jazyce C# nebo Visual Basic mohou přetížení metody přepsatEquals(Object).
Poznámky pro volající
Odvozené třídy často přepisují metodu Object.Equals(Object) pro implementaci rovnosti hodnot. Kromě toho typy také často poskytují další silné typ přetížení Equals
metody, obvykle implementací IEquatable<T> rozhraní. Při volání Equals
metody pro testování rovnosti byste měli vědět, jestli aktuální instance přepisuje Object.Equals a rozumí tomu, jak se řeší konkrétní volání Equals
metody. V opačném případě můžete provést test rovnosti, který se liší od toho, co jste chtěli, a metoda může vrátit neočekávanou hodnotu.
V následujícím příkladu je uvedena ukázka. Vytvoří instanci tří StringBuilder objektů s identickými řetězci a pak provede čtyři volání metod Equals
. První volání metody vrátí true
a zbývající tři návraty false
.
using System;
using System.Text;
public class Example
{
public static void Main()
{
StringBuilder sb1 = new StringBuilder("building a string...");
StringBuilder sb2 = new StringBuilder("building a string...");
Console.WriteLine("sb1.Equals(sb2): {0}", sb1.Equals(sb2));
Console.WriteLine("((Object) sb1).Equals(sb2): {0}",
((Object) sb1).Equals(sb2));
Console.WriteLine("Object.Equals(sb1, sb2): {0}",
Object.Equals(sb1, sb2));
Object sb3 = new StringBuilder("building a string...");
Console.WriteLine("\nsb3.Equals(sb2): {0}", sb3.Equals(sb2));
}
}
// The example displays the following output:
// sb1.Equals(sb2): True
// ((Object) sb1).Equals(sb2): False
// Object.Equals(sb1, sb2): False
//
// sb3.Equals(sb2): False
open System
open System.Text
let sb1 = StringBuilder "building a string..."
let sb2 = StringBuilder "building a string..."
printfn $"sb1.Equals(sb2): {sb1.Equals sb2}"
printfn $"((Object) sb1).Equals(sb2): {(sb1 :> obj).Equals sb2}"
printfn $"Object.Equals(sb1, sb2): {Object.Equals(sb1, sb2)}"
let sb3 = StringBuilder "building a string..."
printfn $"\nsb3.Equals(sb2): {sb3.Equals sb2}"
// The example displays the following output:
// sb1.Equals(sb2): True
// ((Object) sb1).Equals(sb2): False
// Object.Equals(sb1, sb2): False
//
// sb3.Equals(sb2): False
Imports System.Text
Module Example
Public Sub Main()
Dim sb1 As New StringBuilder("building a string...")
Dim sb2 As New StringBuilder("building a string...")
Console.WriteLine("sb1.Equals(sb2): {0}", sb1.Equals(sb2))
Console.WriteLine("CObj(sb1).Equals(sb2): {0}",
CObj(sb1).Equals(sb2))
Console.WriteLine("Object.Equals(sb1, sb2): {0}",
Object.Equals(sb1, sb2))
Console.WriteLine()
Dim sb3 As Object = New StringBuilder("building a string...")
Console.WriteLine("sb3.Equals(sb2): {0}", sb3.Equals(sb2))
End Sub
End Module
' The example displays the following output:
' sb1.Equals(sb2): True
' CObj(sb1).Equals(sb2): False
' Object.Equals(sb1, sb2): False
'
' sb3.Equals(sb2): False
V prvním případě se volá přetížení metody silného StringBuilder.Equals(StringBuilder) typu, které testuje rovnost hodnot. Vzhledem k tomu, že řetězce přiřazené k dvěma StringBuilder objektům jsou stejné, vrátí true
metoda . StringBuilder Ale nepřepíše Object.Equals(Object). Z tohoto důvodu, když StringBuilder je objekt přetypován na Object, když StringBuilder je instance přiřazena proměnné typu Objecta při Object.Equals(Object, Object) předání metody dva StringBuilder objekty, je volána výchozí Object.Equals(Object) metoda. Vzhledem k tomu StringBuilder , že jde o typ odkazu, je to ekvivalentem předání dvou StringBuilder objektů metodě ReferenceEquals . I když všechny tři StringBuilder objekty obsahují identické řetězce, odkazují na tři odlišné objekty. V důsledku toho se tyto tři volání metody vrátí false
.
Aktuální objekt můžete porovnat s jiným objektem pro rovnost odkazů voláním ReferenceEquals metody. V Visual Basic můžete také použít is
klíčové slovo (například If Me Is otherObject Then ...
).
Poznámky pro dědice
Když definujete vlastní typ, tento typ dědí funkce definované metodou Equals
základního typu. Následující tabulka uvádí výchozí implementaci Equals
metody pro hlavní kategorie typů v .NET Framework.
Kategorie typu | Rovnost definovaná | Komentáře |
---|---|---|
Třída odvozená přímo z Object | Object.Equals(Object) | Rovnost odkazů; ekvivalentní volání Object.ReferenceEquals. |
Struktura | ValueType.Equals | Rovnost hodnot; buď přímé porovnání bajtů podle bajtů, nebo porovnání polí podle polí pomocí reflexe. |
Výčet | Enum.Equals | Hodnoty musí mít stejný typ výčtu a stejnou podkladovou hodnotu. |
Delegát | MulticastDelegate.Equals | Delegáti musí mít stejný typ se stejnými seznamy volání. |
Rozhraní | Object.Equals(Object) | Rovnost odkazů. |
U typu hodnoty byste měli vždy přepsat Equals, protože testy rovnosti, které spoléhají na reflexi, nabízejí nízký výkon. Můžete také přepsat výchozí implementaci Equals referenčních typů pro testování rovnosti hodnot místo rovnosti odkazů a definovat přesný význam rovnosti hodnot. Takové implementace návratu Equals true
, pokud dva objekty mají stejnou hodnotu, i když nejsou stejnou instancí. Implementátor typu rozhoduje, co představuje hodnotu objektu, ale obvykle se jedná o některá nebo všechna data uložená v proměnných instance objektu. Například hodnota objektu String je založená na znacích řetězce; String.Equals(Object) metoda přepíše Object.Equals(Object) metodu tak, aby se vrátila true
pro všechny dvě instance řetězců, které obsahují stejné znaky ve stejném pořadí.
Následující příklad ukazuje, jak přepsat metodu Object.Equals(Object) pro testování rovnosti hodnot. Přepíše metodu Equals Person
třídy. Pokud by Person
byla přijata implementace rovnosti základní třídy, dva Person
objekty by byly stejné pouze v případě, že odkazují na jeden objekt. V tomto případě jsou však dva Person
objekty stejné, pokud mají stejnou hodnotu pro Person.Id
vlastnost.
public class Person
{
private string idNumber;
private string personName;
public Person(string name, string id)
{
this.personName = name;
this.idNumber = id;
}
public override bool Equals(Object obj)
{
Person personObj = obj as Person;
if (personObj == null)
return false;
else
return idNumber.Equals(personObj.idNumber);
}
public override int GetHashCode()
{
return this.idNumber.GetHashCode();
}
}
public class Example
{
public static void Main()
{
Person p1 = new Person("John", "63412895");
Person p2 = new Person("Jack", "63412895");
Console.WriteLine(p1.Equals(p2));
Console.WriteLine(Object.Equals(p1, p2));
}
}
// The example displays the following output:
// True
// True
open System
type Person(name, id) =
member _.Name = name
member _.Id = id
override _.Equals(obj) =
match obj with
| :? Person as personObj ->
id.Equals personObj.Id
| _ ->
false
override _.GetHashCode() =
id.GetHashCode()
let p1 = Person("John", "63412895")
let p2 = Person("Jack", "63412895")
printfn $"{p1.Equals p2}"
printfn $"{Object.Equals(p1, p2)}"
// The example displays the following output:
// True
// True
Public Class Person
Private idNumber As String
Private personName As String
Public Sub New(name As String, id As String)
Me.personName = name
Me.idNumber = id
End Sub
Public Overrides Function Equals(obj As Object) As Boolean
Dim personObj As Person = TryCast(obj, Person)
If personObj Is Nothing Then
Return False
Else
Return idNumber.Equals(personObj.idNumber)
End If
End Function
Public Overrides Function GetHashCode() As Integer
Return Me.idNumber.GetHashCode()
End Function
End Class
Module Example
Public Sub Main()
Dim p1 As New Person("John", "63412895")
Dim p2 As New Person("Jack", "63412895")
Console.WriteLine(p1.Equals(p2))
Console.WriteLine(Object.Equals(p1, p2))
End Sub
End Module
' The example displays the following output:
' True
' True
Kromě přepsání Equalsmůžete rozhraní implementovat IEquatable<T> tak, aby poskytovalo test silného typu pro rovnost.
Následující příkazy musí být pravdivé pro všechny implementace Equals(Object) metody. V seznamu , x
, y
a z
reprezentovat odkazy na objekty, které nejsou null.
x.Equals(x)
vrátítrue
hodnotu .x.Equals(y)
vrátí stejnou hodnotu jakoy.Equals(x)
.x.Equals(y)
vrátítrue
, pokud jsou oběx
ay
jsouNaN
.Pokud
(x.Equals(y) && y.Equals(z))
se vrátítrue
, vrátíx.Equals(z)
hodnotutrue
.Po sobě jdoucí volání vrátí
x.Equals(y)
stejnou hodnotu, pokud objekty, na kteréx
odkazuje, ay
nejsou změněny.x.Equals(null)
vrátífalse
hodnotu .
Equals Implementace nesmí vyvolat výjimky. Měly by vždy vrátit hodnotu. Pokud je null
například , obj
Equals metoda by se měla vrátit false
místo vyvolání ArgumentNullException.
Při přepsání Equals(Object)postupujte podle těchto pokynů:
Typy, které implementují IComparable , musí přepsat Equals(Object).
Typy, které přepíší Equals(Object) , musí také přepsat GetHashCode; jinak nemusí tabulky hash fungovat správně.
Měli byste zvážit implementaci IEquatable<T> rozhraní pro podporu testů silného typu pro rovnost. Vaše IEquatable<T>.Equals implementace by měla vracet výsledky, které jsou konzistentní s Equals.
Pokud programovací jazyk podporuje přetížení operátoru a přetížíte operátor rovnosti pro daný typ, musíte také přepsat metodu Equals(Object) , aby se vrátil stejný výsledek jako operátor rovnosti. To pomáhá zajistit, aby se kód knihovny tříd, který používá Equals (například ArrayList a Hashtable) chová způsobem, který je konzistentní se způsobem, jakým je operátor rovnosti používán kódem aplikace.
Pokyny pro typy odkazů
Pro typ Equals(Object) odkazu platí následující pokyny:
Zvažte přepsání Equals , pokud sémantika typu vychází ze skutečnosti, že typ představuje některé hodnoty.
Většina referenčních typů nesmí přetížit operátor rovnosti, i když přepíší Equals. Pokud však implementujete odkazový typ, který má mít sémantiku hodnot, například komplexní typ čísla, musíte přepsat operátor rovnosti.
U proměnlivého typu odkazu byste neměli přepisovat Equals . Důvodem je to, že přepsání Equals vyžaduje také přepsání GetHashCode metody, jak je popsáno v předchozí části. To znamená, že kód hash instance proměnlivého referenčního typu se může během své životnosti změnit, což může způsobit ztrátu objektu v tabulce hash.
Pokyny pro typy hodnot
Pro typ hodnoty platí Equals(Object) následující pokyny:
Pokud definujete typ hodnoty, který obsahuje jedno nebo více polí, jejichž hodnoty jsou odkazové typy, měli byste přepsat Equals(Object). Implementace Equals(Object) , kterou ValueType poskytuje, provádí porovnání bajtů bajtů pro typy hodnot, jejichž pole jsou všechny typy hodnot, ale používá reflexi k provedení porovnání typů hodnot podle pole, jejichž pole obsahují odkazové typy.
Pokud přepíšete Equals a vývojový jazyk podporuje přetížení operátoru, musíte přetížit operátor rovnosti.
Měli byste implementovat IEquatable<T> rozhraní. Volání metody silného typu IEquatable<T>.Equals zabrání boxování argumentu
obj
.
Viz také
Platí pro
Equals(Object, Object)
Určuje, zda jsou zadané instance objektů považovány za stejné.
public:
static bool Equals(System::Object ^ objA, System::Object ^ objB);
public static bool Equals (object objA, object objB);
public static bool Equals (object? objA, object? objB);
static member Equals : obj * obj -> bool
Public Shared Function Equals (objA As Object, objB As Object) As Boolean
Parametry
- objA
- Object
První objekt k porovnání
- objB
- Object
Druhý objekt k porovnání
Návraty
true
jsou-li objekty považovány za stejné; false
v opačném případě . Pokud obě objA
a objB
jsou null, metoda vrátí true
.
Příklady
Následující příklad znázorňuje metodu Equals(Object, Object) a porovná ji s metodou ReferenceEquals .
using System;
public class Example
{
public static void Main()
{
Dog m1 = new Dog("Alaskan Malamute");
Dog m2 = new Dog("Alaskan Malamute");
Dog g1 = new Dog("Great Pyrenees");
Dog g2 = g1;
Dog d1 = new Dog("Dalmation");
Dog n1 = null;
Dog n2 = null;
Console.WriteLine("null = null: {0}", Object.Equals(n1, n2));
Console.WriteLine("null Reference Equals null: {0}\n", Object.ReferenceEquals(n1, n2));
Console.WriteLine("{0} = {1}: {2}", g1, g2, Object.Equals(g1, g2));
Console.WriteLine("{0} Reference Equals {1}: {2}\n", g1, g2, Object.ReferenceEquals(g1, g2));
Console.WriteLine("{0} = {1}: {2}", m1, m2, Object.Equals(m1, m2));
Console.WriteLine("{0} Reference Equals {1}: {2}\n", m1, m2, Object.ReferenceEquals(m1, m2));
Console.WriteLine("{0} = {1}: {2}", m1, d1, Object.Equals(m1, d1));
Console.WriteLine("{0} Reference Equals {1}: {2}", m1, d1, Object.ReferenceEquals(m1, d1));
}
}
public class Dog
{
// Public field.
public string Breed;
// Class constructor.
public Dog(string dogBreed)
{
this.Breed = dogBreed;
}
public override bool Equals(Object obj)
{
if (obj == null || !(obj is Dog))
return false;
else
return this.Breed == ((Dog) obj).Breed;
}
public override int GetHashCode()
{
return this.Breed.GetHashCode();
}
public override string ToString()
{
return this.Breed;
}
}
// The example displays the following output:
// null = null: True
// null Reference Equals null: True
//
// Great Pyrenees = Great Pyrenees: True
// Great Pyrenees Reference Equals Great Pyrenees: True
//
// Alaskan Malamute = Alaskan Malamute: True
// Alaskan Malamute Reference Equals Alaskan Malamute: False
//
// Alaskan Malamute = Dalmation: False
// Alaskan Malamute Reference Equals Dalmation: False
open System
// Class constructor
type Dog(dogBreed) =
// Public property.
member _.Breed = dogBreed
override this.Equals(obj) =
match obj with
| :? Dog as dog when dog.Breed = this.Breed -> true
| _ -> false
override _.GetHashCode() =
dogBreed.GetHashCode()
override _.ToString() =
dogBreed
let m1 = Dog "Alaskan Malamute"
let m2 = Dog "Alaskan Malamute"
let g1 = Dog "Great Pyrenees"
let g2 = g1
let d1 = Dog "Dalmation"
let n1 = Unchecked.defaultof<Dog>
let n2 = Unchecked.defaultof<Dog>
printfn $"null = null: {Object.Equals(n1, n2)}"
printfn $"null Reference Equals null: {Object.ReferenceEquals(n1, n2)}\n"
printfn $"{g1} = {g2}: {Object.Equals(g1, g2)}"
printfn $"{g1} Reference Equals {g2}: {Object.ReferenceEquals(g1, g2)}\n"
printfn $"{m1} = {m2}: {Object.Equals(m1, m2)}"
printfn $"{m1} Reference Equals {m2}: {Object.ReferenceEquals(m1, m2)}\n"
printfn $"{m1} = {d1}: {Object.Equals(m1, d1)}"
printfn $"{m1} Reference Equals {d1}: {Object.ReferenceEquals(m1, d1)}"
// The example displays the following output:
// null = null: True
// null Reference Equals null: True
//
// Great Pyrenees = Great Pyrenees: True
// Great Pyrenees Reference Equals Great Pyrenees: True
//
// Alaskan Malamute = Alaskan Malamute: True
// Alaskan Malamute Reference Equals Alaskan Malamute: False
//
// Alaskan Malamute = Dalmation: False
// Alaskan Malamute Reference Equals Dalmation: False
Module Example
Public Sub Main()
Dim m1 As New Dog("Alaskan Malamute")
Dim m2 As New Dog("Alaskan Malamute")
Dim g1 As New Dog("Great Pyrenees")
Dim g2 As Dog = g1
Dim d1 As New Dog("Dalmation")
Dim n1 As Dog = Nothing
Dim n2 As Dog = Nothing
Console.WriteLine("null = null: {0}", Object.Equals(n1, n2))
Console.WriteLine("null Reference Equals null: {0}", Object.ReferenceEquals(n1, n2))
Console.WriteLine()
Console.WriteLine("{0} = {1}: {2}", g1, g2, Object.Equals(g1, g2))
Console.WriteLine("{0} Reference Equals {1}: {2}", g1, g2, Object.ReferenceEquals(g1, g2))
Console.WriteLine()
Console.WriteLine("{0} = {1}: {2}", m1, m2, Object.Equals(m1, m2))
Console.WriteLine("{0} Reference Equals {1}: {2}", m1, m2, Object.ReferenceEquals(m1, m2))
Console.WriteLine()
Console.WriteLine("{0} = {1}: {2}", m1, d1, Object.Equals(m1, d1))
Console.WriteLine("{0} Reference Equals {1}: {2}", m1, d1, Object.ReferenceEquals(m1, d1))
End Sub
End Module
Public Class Dog
' Public field.
Public Breed As String
' Class constructor.
Public Sub New(dogBreed As String)
Me.Breed = dogBreed
End Sub
Public Overrides Function Equals(obj As Object) As Boolean
If obj Is Nothing OrElse Not typeof obj Is Dog Then
Return False
Else
Return Me.Breed = CType(obj, Dog).Breed
End If
End Function
Public Overrides Function GetHashCode() As Integer
Return Me.Breed.GetHashCode()
End Function
Public Overrides Function ToString() As String
Return Me.Breed
End Function
End Class
' The example displays the following output:
' null = null: True
' null Reference Equals null: True
'
' Great Pyrenees = Great Pyrenees: True
' Great Pyrenees Reference Equals Great Pyrenees: True
'
' Alaskan Malamute = Alaskan Malamute: True
' Alaskan Malamute Reference Equals Alaskan Malamute: False
'
' Alaskan Malamute = Dalmation: False
' Alaskan Malamute Reference Equals Dalmation: False
Poznámky
Statická Equals(Object, Object) metoda označuje, zda jsou dva objekty a objB``objA
, jsou rovny. Umožňuje také testovat objekty, jejichž hodnota je null pro rovnost. Porovnává objA
rovnost objB
následujícím způsobem:
Určuje, zda dva objekty představují stejný odkaz na objekt. Pokud ano, metoda vrátí
true
. Tento test je ekvivalentní volání ReferenceEquals metody. Kromě toho, pokud oběobjA
aobjB
jsou null, metoda vrátítrue
.Určuje, jestli má hodnotu
objA
objB
null. Pokud ano, vrátífalse
.Pokud dva objekty nepředstavují stejný odkaz na objekt a ani jeden není null, volá
objA
.Equals
(objB
) a vrátí výsledek. To znamená, že pokudobjA
přepíše metodu Object.Equals(Object) , volá se toto přepsání.