编程语言
首页 > 编程语言> > 在C#中访问通用值类型的成员

在C#中访问通用值类型的成员

作者:互联网

我正在编写一个C#程序,该程序在多个坐标系中进行计算,并在它们之间进行转换.为了避免混淆,我想对每种坐标使用单独的静态值类型.例如:

struct FooSpaceCoords {
    double x, y, z;
}

struct BarSpaceCoords {
    double x, y, z;
}

现在,方便且类型安全的矩阵类将是不错的选择.但是以下情况不起作用:

 public class MatrixTransform<To, From> where To : struct, From : struct 
 {
    .... some implementation that requires .x, .y and .z ....
 }

之所以失败,是因为编译器无法知道To和From具有成员.x,.y& .z.

我可以定义一个IHaveXYZ接口,但是在我看来,这将导致很多装箱操作,这违背了整个计划的精神(如果这样重要,则效率较低).

有一种简单的方法可以完成我原来想要的吗?

解决方法:

I could define an IHaveXYZ interface, but it seems to me that that will result in a lot of boxing operations which defies the spirit of the whole plan (and is less effecient, if that matters).

不,不会-如果您使用通用类型约束,则生成的IL不会装箱/拆箱.例如:

interface IFoo
{
    void Foo();
}

struct Bar : IFoo
{
    public void Foo()
    {
        // Do something
    }
}

class Test
{
    static void DoFoo<T>(T value) where T : IFoo
    {
        value.Foo();
    }

    static void Main()
    {
        Bar bar = new Bar();
        DoFoo(bar); // No boxing involved
    }
}

DoFoo的IL如下所示:

.method private hidebysig static void  DoFoo<(IFoo) T>(!!T 'value') cil managed
{
  // Code size       16 (0x10)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ldarga.s   'value'
  IL_0003:  constrained. !!T
  IL_0009:  callvirt   instance void IFoo::Foo()
  IL_000e:  nop
  IL_000f:  ret
} // end of method Test::DoFoo

注意“约束”部分.根据ECMA-335第I.8.2.4节:

Boxing and unboxing of generic arguments adds performance overhead to a CLI implementation. The constrained. prefix can improve performance during virtual dispatch to a method defined by a value type, by avoiding boxing the value type.

重要的是,您不要仅将价值称为IFoo.这行将装箱值(当T为值类型时):

IFoo copy = value; // Might box

只要您坚持使用泛型类型参数,就应该可以.

标签:generics,coordinate-systems,c
来源: https://codeday.me/bug/20191030/1968380.html