IEqualityComparer ReferenceEquals를 사용하는
IEqualityComparer<T>
사용 하는 기본 구현이 ReferenceEquals
있습니까?
EqualityComparer<T>.Default
를 사용하는 ObjectComparer를 사용합니다 object.Equals()
. 제 경우에는 객체가 이미 구현되어 있으므로 IEquatable<T>
객체의 참조로만 무시하고 비교해야합니다.
기본 구현이없는 경우를 대비하여 다음과 같습니다.
280Z28에 의해 편집 :를 사용하는 이유. RuntimeHelpers.GetHashCode(object)
많은 분들이 이전에 본 적이 없을 것입니다. :)이 메서드는 이 구현에 대한 올바른 호출을 만드는 두 가지 효과가 있습니다 .
- 객체가 null이면 0을 반환합니다. 이후
ReferenceEquals
널 매개 변수에 대한 작품, 그래서해야 GetHashCode의 비교 자 구현 (). Object.GetHashCode()
가상으로 호출 하지 않습니다.ReferenceEquals
특히는의 모든 재정의를 무시Equals
하므로 GetHashCode () 구현에서는 RuntimeHelpers.GetHashCode의 용도 인 ReferenceEquals 효과와 일치하는 특수 메서드를 사용해야합니다.
[280Z28 종료]
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
/// <summary>
/// A generic object comparerer that would only use object's reference,
/// ignoring any <see cref="IEquatable{T}"/> or <see cref="object.Equals(object)"/> overrides.
/// </summary>
public class ObjectReferenceEqualityComparer<T> : EqualityComparer<T>
where T : class
{
private static IEqualityComparer<T> _defaultComparer;
public new static IEqualityComparer<T> Default
{
get { return _defaultComparer ?? (_defaultComparer = new ObjectReferenceEqualityComparer<T>()); }
}
#region IEqualityComparer<T> Members
public override bool Equals(T x, T y)
{
return ReferenceEquals(x, y);
}
public override int GetHashCode(T obj)
{
return RuntimeHelpers.GetHashCode(obj);
}
#endregion
}
이전 답변 구현을 .Net4.0 +로 업데이트해야 할 때라고 생각했습니다. 여기서 IEqualityComparer<in T>
인터페이스의 반 변성 덕분에 비 제네릭이되어 단순화됩니다 .
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
public sealed class ReferenceEqualityComparer
: IEqualityComparer, IEqualityComparer<object>
{
public static readonly ReferenceEqualityComparer Default
= new ReferenceEqualityComparer(); // JIT-lazy is sufficiently lazy imo.
private ReferenceEqualityComparer() { } // <-- A matter of opinion / style.
public bool Equals(object x, object y)
{
return x == y; // This is reference equality! (See explanation below.)
}
public int GetHashCode(object obj)
{
return RuntimeHelpers.GetHashCode(obj);
}
}
이제 T
이전의 경우처럼 각 유형에 대해 하나씩이 아니라 모든 참조 같음 검사를 위해 하나의 인스턴스 만 있으면됩니다 .
또한 T
이것을 사용하고 싶을 때마다 지정하지 않아도 되므로 타이핑을 절약 할 수 있습니다!
To clarify for those who are not familiar with the concepts of Covariance and Contravariance...
class MyClass
{
ISet<MyClass> setOfMyClass = new HashSet<MyClass>(ReferenceEqualityComparer.Default);
}
...will work just fine. This is not limited to e.g. HashSet<object>
or similar (in .Net4.0).
Also for anyone wondering why x == y
is reference equality, it is because the ==
operator is a static method, which means it is resolved at compile-time, and at compile-time x and y are of type object
so here it resolves to the ==
operator of object
- which is the real reference equality method. (In fact the Object.ReferenceEquals(object, object)
method is simply a redirect to the object equals operator.)
Here's a simple implementation for C# 6.
public sealed class ReferenceEqualityComparer : IEqualityComparer, IEqualityComparer<object>
{
public static ReferenceEqualityComparer Default { get; } = new ReferenceEqualityComparer();
public new bool Equals(object x, object y) => ReferenceEquals(x, y);
public int GetHashCode(object obj) => RuntimeHelpers.GetHashCode(obj);
}
EDIT (You don't have to read this unless you're interested in the comments below)
@AnorZaken devoted many paragraphs to the three letters of the new
modifier here. Let's summarise.
The single defined instance Equals(object,object)
method implements the Equals
method of the two declared interfaces for this type, IEqualityComparer
and its generic counterpart IEqualityComparer<object>
. The signatures are identical, so this definition satisfies both interfaces.
The instance method ReferenceEqualityComparer.Equals(object,object)
hides the static object.Equals(object,object)
method.
Without new
the compiler warns about this. What does this actually mean?
It means that if you want to call the static object.Equals
methods, you cannot call it on an instance of ReferenceEqualityComparer
. Is this a big deal?
No. In fact it's desired behaviour. It means that if you want to call object.Equals(a,b)
you cannot do it via code such as ReferenceEqualityComparer.Default.Equals(a,b)
. That code is clearly requesting reference equality -- no one would reasonably expect it to perform default/value equality. Why wouldn't you just code the more explicit object.Equals(a,b)
anyway? So the use of new
provides sensible and desirable behaviour, and allows compilation with no warnings.
How else could you suppress the warning? If you use a #pragma warning disable 108
/#pragma warning restore 108
then the outcome is the same as using new
, except you've added a bunch more noise to your code. new
suffices and explains the intent more clearly to others.
Alternatively you could use explicit implementations for the two interface Equals
methods, but then if you used ReferenceEqualityComparer.Default.Equals(a,b)
you wouldn't have reference equality at all.
In reality, hiding static methods with instance methods is rarely a problem because static methods are dereferenced from a type specifier, not an instance specifier. That is, you use Foo.StaticMethod()
not new Foo().StaticMethod()
. Calling static methods from instances is unnecessary at best and misleading/incorrect at worst.
Further, for equality comparers, you rarely use their concrete types directly. Rather, you use them with APIs such as collections.
So whilst this was an interesting and at times confusing discussion, it was rather fruitless.
Microsoft provide ObjectReferenceEqualityComparer
in System.Data.Entity.Infrastructure
. Just use ObjectReferenceEqualityComparer.Default
as comparer.
ReferenceURL : https://stackoverflow.com/questions/1890058/iequalitycomparert-that-uses-referenceequals
'Development Tip' 카테고리의 다른 글
Haskell 상태 모나드를 사용하면 코드 냄새가나요? (0) | 2020.12.25 |
---|---|
Java EE 웹 애플리케이션에서 WEB-INF는 무엇을 의미합니까? (0) | 2020.12.25 |
CSS 호버는 모바일 장치에서 작동합니까? (0) | 2020.12.25 |
Enum을 데이터베이스에 저장하는 가장 좋은 방법 (0) | 2020.12.25 |
어떤 무료 SQL 서식 도구가 있습니까? (0) | 2020.12.25 |