C#会从聚合结构/类中受益吗?

时间:2011-01-18 06:30:00

标签: c# class struct aggregate

3 个答案:

答案 0 :(得分:5)

我希望结构首先用你提出的语义来定义。

然而,我们仍然坚持我们现在所拥有的东西,我认为我们不太可能在CLR中获得全新的“类型”。引入一种新类型意味着将它引入每种 .NET语言,而不仅仅是C#,这是一个很大的变化。

我认为更有可能 - 并且请记住,当我谈到假设的,未经宣布的未来产品的假设语言特征,这些产品不存在且可能永远不存在时,我这样做仅用于娱乐目的< / em> - 我们会找到一些方法来对类和结构进行更好的不变性注释和强制执行。无论所讨论的类型是值类型还是引用类型,编译器都可以更好地执行不变性并使其更容易以不可变样式进行编程。如果在编译时或jit时间有更多的不变性保证,那么编译器或CLR也可以更好地优化在多核机器上运行的代码。

虽然您正在考虑提案,但您可能需要考虑的一个有趣问题是:如果聚合类型有方法,则“this”是变量?例如:

aggregate Vector
{
    int x, y, z;
    public void M(Action action)
    {
         Console.WriteLine(this.x);
         action();
         Console.WriteLine(this.x);
    }
}
...
Vector v = new Vector(1, 2, 3);
Action action = ()=>{ v = new Vector(4, 5, 6); };
v.M(action);

会发生什么? “this”是否通过 value 传递给M,在这种情况下,它会两次写出“1”,或者它是否作为对变量的引用传递,其中如果你所谓的“不可变”类型被观察到变异? (因为变异的是变量;根据定义,变量允许变异,这就是为什么它们被称为“变化能力”。)

答案 1 :(得分:2)

这会做什么?

List<Vector> vectors = ...;
Vector v = vectors[4];
v.Y = 10;

还是这个?

Vector The5thVector(List<Vector> vectors) { return vectors[4]; }
...
List<Vector> vectors = ...;
The5thVector(vectors).Y = 10;

用隐式赋值替换诊断不会让你走得太远。有一个原因可变结构是如此有问题,简单地声明一个新的概念,聚合,不会解决任何这些问题。

最好的解决方案是首先禁止语言中的可变结构。第二个最佳解决方案是表现得好像被禁止一样。结构应该是小而自足的,这消除了使它们不可变的任何缺点。

答案 2 :(得分:1)

不,它不会受益。无论如何,结构都是可变的类型。

首先......“隐含重新分配的不可变性”实际上只是“低效的可变性”。

给定“Point”结构,如果您只想更改X的值,为什么强制重写整个内存结构?仅仅覆盖X比使用新值覆盖X并且用其当前值无意义地覆盖Y更有效。这样的计划没有任何好处。

老实说,可变性的整个主题是一个透视问题。当引用一个复杂的对象作为一个整体,并且在保持对整个对象的引用时,询问它的各个部分是否会改变值,这真的是有意义的。

例如,调用字符串不可变是有意义的,因为您将其称为表示字符集合的特定内存块,其中字符不会从具有引用的任何内容的角度更改值它。另一方面,int结构是可变的,因为它的值可以通过简单赋值来改变,并且任何int结构的引用(指针)都将看到这些更改。

对于struct或aggregate方法中的“this”,当然它应该始终引用堆栈上的struct / aggregate的内存位置,因此应该反映和看到通过匿名方法和更改struct的值的委托进行的更新。可变的。总而言之,可变性在基本变量级别是一个好主意,并且不可变性最好在更高级别处理,其中复杂对象被表示并且“不可变”行为被明确编码。