2009-06-07 18 views
8

Her veri sınıfını yazdığımda, genellikle IEquatable uygulamasını yazarken çok fazla zaman harcıyorum.Yöntem uygulama yardımcılarına eşittir (C#)

public class Polygon 
{ 
    public Point[] Vertices { get; set; } 
} 

Uygulama IEquatable exaustive oldu:

yazdım son sınıf gibi bir şey oldu. Kesinlikle C# 3.0/LINQ çok yardımcı olur, ancak köşeler kaydırılabilir ve/veya ters sırada olabilir ve bu Equals yöntemine çok fazla karmaşıklık katar. Birçok ünite testinden ve karşılık gelen uygulamadan vazgeçtim ve başvurumu sadece üçlü kabul etmeye karar verdim, ki bu da IEquatable uygulamasının tamamen kapsanması için sadece 11 birim test gerektirdi.

Equals ve GetHashCode'un uygulanmasına yardımcı olan herhangi bir araç veya teknik var mı?

+0

kod nesil Eşittir, ama genel bir algoritma Uygulayacak kişi için. Galiba burada şansın yok. – erikkallen

cevap

8

Eşitlik üyeleri oluşturmak için ReSharper kullanıyorum. İsterseniz, isteğe bağlı olarak IEquatable<T> ve geçersiz kılan operatörleri de kullanabilirsiniz (tabi ki hiç bir zaman yapmazsınız, ancak yine de iyidir).

Eşittirlerin uygulanması, Object.Equals(Object) bir geçersiz kılma ile birlikte, güçlü yazılan bir varyantı (gereksiz tür denetimini önleyebilir) içerir. Daha az yazılan sürüm, tip kontrolü yaptıktan sonra güçlü bir şekilde yazılanı çağırır. Güçlü yazılan sürüm, bir referans eşitlik denetimi (Object.ReferenceEquals(Object,Object)) gerçekleştirir ve daha sonra tüm alanların değerlerini (iyi, yalnızca jeneratörü dahil edeceğini söyleyenler) karşılaştırır. GetHashCode gelince

, alanın GetHashCode değerlerinin bir akıllı factorisation (eğer derleyici 'checked seçeneğini kullanırsanız taşma durumları önlemek için unchecked kullanarak) birleştirilir. Her alanın değerleri (birinciden ayrı olarak) birleştirilmeden önce asal sayılarla çarpılır. Ayrıca hangi alanların asla boş kalacağını belirtebilirsiniz ve herhangi bir null çek içermeyecektir. İşte

sonra " Eşitlik Üyeler üret" seçilerek ALT+Insert basarak Polygon sınıf için elde ne:

tek alan
public class Polygon : IEquatable<Polygon> 
{ 
    public Point[] Vertices { get; set; } 

    public bool Equals(Polygon other) 
    { 
     if (ReferenceEquals(null, other)) return false; 
     if (ReferenceEquals(this, other)) return true; 
     return Equals(other.Vertices, Vertices); 
    } 

    public override bool Equals(object obj) 
    { 
     if (ReferenceEquals(null, obj)) return false; 
     if (ReferenceEquals(this, obj)) return true; 
     if (obj.GetType() != typeof (Polygon)) return false; 
     return Equals((Polygon) obj); 
    } 

    public override int GetHashCode() 
    { 
     return (Vertices != null ? Vertices.GetHashCode() : 0); 
    } 
} 

Ben geçerli değildir, yukarda bahsettiğim özelliklerden bazıları olarak orada . Dizinin içeriğini kontrol etmediğini de unutmayın. Yine de, ReSharper, genel olarak birkaç saniyede bir çok mükemmel kodu dışarıda pompalamaktadır. Ve bu özellik ReSharper'ı inanılmaz bir araç haline getiren şeyler listemde oldukça düşük.

+0

Büyülü değil ama kesinlikle yardımcı oluyor! Teşekkürler –

+2

Bu Equals (obj) geçersiz kılma bana mükemmel bir kod gibi görünmüyor. Bu geri dönmek için daha doğal olmaz mı? (Polygon olarak obj); – mquander

+0

Belki de okunması daha basit kod, evet. Ancak performans özellikleri daha kötü olurdu. JIT, ilk satırı basit bir makine kodu talimatına (sıfır ile cmp) indirecek ve bu da çok hızlı çalışacak.İkinci satır, çalıştırmak için çok hızlı olacak başka bir basit makine kodu talimatına (cmp obj işaretçileri) indirger. Üçüncü satır, bir tür denetimi yapar (JIT, nesnenin tip koduna göre başka bir işaretçi kontrolüne kadar bunu en iyi duruma getirir) ve son olarak yukarıdaki kontroller başarısız olursa, aslında eşittir. –

2

Öğelerin iki dizisini karşılaştırırken, SequenceEqual uzantı yöntemini kullanıyorum.

Genel Equals ve GetHashCode'a gelince, sizin için çalışabilecek serileştirmeye dayalı bir teknik var. Sen arayan edilemez görünüyor

Using MemoryStream and BinaryFormatter for reuseable GetHashCode and DeepCopy functions

+0

Araç setime eklediğiniz için teşekkürler. –

+0

3.5/System.Core.dll'de SequenceEqual bulamadım, nerede olduğunu biliyor musunuz? Kaynak kodunu görüntülemek için Red Gate'in Reflektörünü kullanıyorum. –

+0

Harika bir yazı! Şimdi, Equals uygulamasını yazmanın aptalca olduğunu anladım, tek yapmanız gereken GetHashCode'u uygulamak ve sonra Equals'ta kullanmak. –