Home > Software design >  Implement generic interface method in generic class
Implement generic interface method in generic class

Time:11-24

Is there any way to implement the interface ISetter so that I do not need boxing when assigning the value? A direct cast (T)value is obviously not possible (compiler error). Type T can be a value or a class type. The interface ISetter must not be generic itself as it should be used as value type in a common dictionary for different types T.

public interface ISetter
{
    void Set<T>(T value);
}

public class Prop<T> : ISetter
{
    public T Value;

    //will be called always matching T1 == T
    public void Set<T1>(T1 value)
    {
        if (typeof(T1) != typeof(T)) throw new ArgumentException();
        Value = (T)(object)value;   //is there any way to avoid boxing 
    }
}

CodePudding user response:

To my knowledge it actually should not box the passed value. Every combination of T and T1 where both are value types should be compiled separately so compiler has ability to optimize parts of the code resulting in the removal of the "intermediate" cast to object.

Next benchmark (using BenchmarkDotNet) shows no allocations on my machine (TargetFramework - netcoreapp3.1 with latest SDK installed):

[SimpleJob(RunStrategy.Monitoring)]
[MemoryDiagnoser]
public class BenchBoxedNonBoxedGeneric
{
    private static Prop<int> GenericProp = new();
    private static Prop NonGenericProp = new();
    private const int Iterations = 1000_000_000;

    
    [Benchmark]
    public int NonGeneric()
    {
        for (int i = 0; i < Iterations; i  )
        {
            NonGenericProp.Set(i);
        }

        return NonGenericProp.Value;
    }

    [Benchmark]
    public int Generic()
    {
        for (int i = 0; i < Iterations; i  )
        {
            GenericProp.Set(i);
        }

        return GenericProp.Value;
    }

}

public class Prop<T> 
{
    public T Value;

    public void Set<T1>(T1 value)
    {
        Value = (T)(object)value;
    }
}

public class Prop
{
    public int Value;

    public void Set(int value)
    {
        Value = value;
    }
}
Method Mean Error StdDev Allocated
NonGeneric 405.2 ms 26.76 ms 17.70 ms -
Generic 383.2 ms 21.37 ms 14.14 ms -

The decompilation to JIT Asm with sharplab.io seems to prove it too.

  • Related