2009-07-31 83 views
2

考虑以下情形:.NET中的包装类型:struct或class?

int Caller1<T>(T t) where T : IInterface {...} 
T Caller2<T>() where T : IInterface {...} 

class Wrappee // doesn't implement IInterface, but could 

??? Wrapper : IInterface { 
    private readonly Wrappee _wrappee; 

    // methods call _wrappee's methods 
} 

现在,一般建议为structclass之间选择的是“使用struct如果您需要参考的语义值语义和class”。我们需要的语义是“参考Wrappee”。但是看起来我们仍然可以制作一个结构体:拷贝它的值是一样的,就像拷贝一个Wrappee的引用一样,并且这个拷贝将会有一个引用的相同的对象!开销较低,并且scalar replacement可能能够将局部变量降至零。在_wrappee上调用甚至是变异方法似乎都是正确的。

我错过了什么?是否有充分的理由让Wrapper成为一堂课?

有一个,如果来电者是不是通用的:

int Caller(IInterface t) {...} 

在这种情况下Wrapper应该是一个类来避免装箱。

有关Haskell知道的人的备注:我正在尝试找到与newtype最接近的.NET模拟器。

更新:见Professional .NET 2.0 GenericsPeter Ritchie on MSDN forums在第一种情况下没有拳击。

+0

为什么你认为使用结构作为泛型类型参数会影响拳击的需求? – 2009-07-31 18:13:36

+0

查看更新。 – 2009-07-31 18:49:49

回答

2

通常你的类/结构会被你调用的方法(你没有显示Caller1和Caller2做什么)在内部存储或传递,在这种情况下,它可能会被装箱。可能比您预期的更频繁。所以除非你能证明一个结构将会更有效率:不要打扰并且坚持一个类。

此外,除非结构代表某种类型的数据类型,否则结构往往会被忽略,因此选择一个类可能会阻止今后讨论不同的性质。

然而,如果性能是真的一个问题,如果你能保证情况下,仅作为一个泛型类型约束参数传递,并不会存储接口类型的字段或集合,结构的当前内联由.NET运行时将更有效率,因为你的包装结构将主要被优化。但是,这是很多ifs。

0

我会说类,因为你封装行为,而不仅仅是数据。

4

是的,因为您将通过IInterface变量访问包装,为了避免装箱,它应该是一个类。

编辑:如果你通过一个类型为Wrapper的变量来访问包装,并且访问Wrapper方法,而不是IInterface方法,那么一个结构很好。