从实现结构而无需装箱的情况下调用C#接口默认方法 [英] Calling C# interface default method from implementing struct without boxing

查看:57
本文介绍了从实现结构而无需装箱的情况下调用C#接口默认方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我唯一能想到的如下,这远非理想:

The only thing I can think of is as follows, which is far from ideal:

interface IBar {
    void Foo() => Console.WriteLine("Hello from interface!");
}

struct Baz : IBar {
    // compiler error
    void Test1() => this.Foo();

    // IIRC this will box
    void Test2() => ((IBar)this).Foo();

    // this shouldn't box but is pretty complicated just to call a method
    void Test3() {
        impl(ref this);

        void impl<T>(ref T self) where T : IBar
            => self.Foo();  
    }
}

有更简单的方法吗?

(有关此问题以及我的解决方法:调用实现类的C#接口默认方法)

(Related and how I got to this question: Calling C# interface default method from implementing class)

推荐答案

我认为没有任何分配.此答案对此到PR的链接实现了这一点.

I don't think there are any allocations. This answer to this possibly duplicate question explains that the JIT compiler can avoid boxing in many cases, including explicit interface implementation calls. Andy Ayers from the JIT team verified this in a comment and provided a link to the PR that implemented this.

我修改了该答案中的代码:

I adapted the code in that answer :

using System;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;

namespace DIMtest
{
    interface IBar {
        int Foo(int i) => i;
    }

    struct Baz : IBar {
        //Does this box?        
        public int  Test2(int i) => ((IBar)this).Foo(i);
    }


    [MemoryDiagnoser, CoreJob,MarkdownExporter]
    public class Program
    {
        public static void Main() => BenchmarkRunner.Run<Program>();

        [Benchmark]
        public int ViaDIMCast()
        {
            int sum = 0;
            for (int i = 0; i < 1000; i++)
            {
                sum += (new Baz().Test2(i));
            }

            return sum;
        }
    }

}

结果未显示任何分配:


BenchmarkDotNet=v0.11.5, OS=Windows 10.0.18956
Intel Core i7-3770 CPU 3.40GHz (Ivy Bridge), 1 CPU, 8 logical and 4 physical cores
.NET Core SDK=3.0.100-preview9-014004
  [Host] : .NET Core 3.0.0-preview9-19423-09 (CoreCLR 4.700.19.42102, CoreFX 4.700.19.42104), 64bit RyuJIT
  Core   : .NET Core 3.0.0-preview9-19423-09 (CoreCLR 4.700.19.42102, CoreFX 4.700.19.42104), 64bit RyuJIT

Job=Core  Runtime=Core  

|     Method |     Mean |    Error |   StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|----------- |---------:|---------:|---------:|------:|------:|------:|----------:|
| ViaDIMCast | 618.5 ns | 12.05 ns | 13.40 ns |     - |     - |     - |         - |

我将返回类型更改为int,就像链接的答案一样,以确保不会对方法进行优化

I changed the return type to an int just like the linked answer to ensure the method won't be optimized away

这篇关于从实现结构而无需装箱的情况下调用C#接口默认方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆