简体   繁体   中英

How can I avoid boxing when pass a struct value as an interface value?

Interface (I) is a reference type, struct (S) is a value type. Structs can implement interfaces.

public interface I {}
struct S: I {}

Assume there is a value of S which is passed to a method as an argument of I. In this case it has to be boxed.

void Method(I i) {}

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

Is there a way to avoid boxing in this case?

You can avoid boxing if you change the definition of Method to:

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

This avoids boxing, because at runtime the CLR specialises generic methods based on the type of the generic argument(s). Reference types can all share the same implementation, while struct types each get their own version. This means all the operations in Method which depend on T will take into account the size of the concrete struct type.

You must be careful however, since calling virtual methods defined on System.Object like Equals or GetHashCode will cause i to be boxed since virtual method dispatch requires a method table pointer (although the JIT may be able to do the dispatch statically in some cases). However, if your struct type overrides the virtual method(s) in question, then boxing will not need to be done, since the method to call is again known statically since structs (and hence their members) are sealed.

Usually you can avoid calling Equals or GetHashCode directly by constraining T further to implement IEquatable<T> and using an IEqualityComparer<T> for comparisons eg

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

Use generics:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM