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

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

public interface I {} struct S: I {} 

Suppose that there is a value of S that is passed to the method as argument I. In this case, it must be placed in a box.

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

Is there a way to avoid boxing in this case?

+6
source share
2 answers

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

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

This avoids boxing, since at runtime the CLR specializes in generic methods based on the type of generic arguments. Link types can use the same implementation, while structure types get their own version. This means that all operations in Method that depend on T will take into account the size of a particular type of structure.

However, you should be careful, since invoking virtual methods defined in System.Object , for example Equals or GetHashCode , will cause i be boxed, since a method table pointer is required to send the virtual method (although JIT may be able to to send statics in some cases). However, if your type of structure overrides the virtual method (s) in question, then boxing will not need to be done, since the invocation method is again known statically, since the structures (and therefore their members) are sealed.

You can usually avoid directly calling Equals or GetHashCode by restricting T to implement IEquatable<T> and using IEqualityComparer<T> for comparison, for example.

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

Use generics:

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

Source: https://habr.com/ru/post/949410/


All Articles