2013-07-14 16 views
6

Arabirim (I) bir referans türüdür, struct (S) bir değer türüdür. Yapılar arayüzleri uygulayabilir.Yapı değeri bir arabirim değeri olarak geçerken nasıl bokstan kurtulabilirim?

public interface I {} 
struct S: I {} 

bu kutu gereken Bu durumda, I, bir değişken olarak bir yönteme geçirilen bir S değeri vardır varsayalım.

void Method(I i) {} 

void Test() { 
    var s = new S(); 
    this.Method(s); // <---- boxing! 
} 

Bu durumda bokstan kurtulmanın bir yolu var mı?

+1

... ben neden bu işleri tek –

cevap

14

size Method tanımını değiştirirseniz Boksu önleyebilirsiniz:

void Method<T>(T i) where T : I 
{ 
} 

zamanında CLR jenerik argüman (lar) türüne göre genel yöntemler uzmanlaşmış çünkü bu, boks önler. Referans türlerinin hepsi aynı uygulamayı paylaşabilirken, yapı türleri her birinin kendi versiyonunu alır. Bu, T numaralı Method'daki tüm işlemlerin, beton yapı türünün boyutunu dikkate alacağı anlamına gelir.

sanal yöntem sevk beri kutulu edilecek i neden olacaktır Equals veya GetHashCode gibi System.Object tanımlanan sanal yöntemleri çağırmadan beri Ancak dikkatli olmalı JIT bazı statik sevk yapmak mümkün olabilir rağmen (bir yöntem tablo işaretçisi gerektirir

durumlar). Bununla birlikte, yapınızın türü, söz konusu sanal yöntemi/yöntemleri geçersiz kılarsa, yapmanın (ve dolayısıyla üyelerinin) mühürlendiğinden, çağrılacak yöntem tekrar statik olarak bilindiğinden, kutunun yapılması gerekmeyecektir. Genellikle

doğrudan IEquatable<T> uygulamak için ayrıca T kısıtlayıcı ve örneğin karşılaştırmalar için bir IEqualityComparer<T> kullanarak Equals veya GetHashCode arayarak önleyebilirsiniz

void Method<T>(T i) where T : I, IEquatable<T> 
{ 
    T other = ... 
    if(i.Equals(other)) //avoids boxing 
    { 
    } 
} 
+0

açıkça açıklayabilir unutmayın çalışacağım için potansiyel bir görüşme soru gibi geliyor? –

+0

Yapı kısıtlamasını unuttun mu? Burada T: struct, I –

+0

@BradRem: Geçtiğinizde derleme zamanında türünüzü biliyorsanız, C# türü çıkarımı devreye girecek ve "Yöntem (s);" şeklinde adlandırılacaktır. Bu noktada bir yapı kullandığınızı ve bokstan kaçınacağınızı kabul etti. DÜZENLEME: Ancak, derleme zamanında 's' türünü bilmiyorsanız (yani, sadece arayüz olarak yazdınız mı? Yazarak söyleyeyim:' I = yeni S() ') o zaman yine de kutulu (Tabii ki, bu noktada _already_ kutulu yani çok fazla değil) –

0

Kullanım jenerik:

public interface I {} 
pubic struct S : I {} 
public class Foo 
{ 
    public static void Bar<T>(T i) 
     where T : I 
    {} 
} 
İlgili konular