的限制是什么
public class A
{
public string Stuff {get;set;}
}
...
repository.GetAll().Select(x=> new A { x.Stuff });
这不起作用。你必须添加
{ Stuff = x.Stuff }
repository.GetAll().Select(x=> new { x.Stuff });
但这很有效。它创建了一个与A类非常相似的匿名类。
从概念上讲,我认为这里的情况并没有太大差异。任何人都有所了解?
答案 0 :(得分:3)
简短的回答 - C#编译器和语言团队没有这样实现 - 他们要么没有想到它(不太可能),要么认为这不是一个好主意....
repository.GetAll().Select(x=> new A { x.Stuff });
这不起作用。你必须添加
这是一个对象初始化器。这可以通过调用对象的默认构造函数,然后将属性名称与值匹配,即:Stuff = x.Foo
,并且实际上只是匹配属性的快捷方式,因此语法实际上只是“简短”:
A tmp = new A();
tmp.Stuff = x.Stuff;
现在,我想编译器团队可以假设在方程式上没有左侧的初始化语句应该搜索名称匹配和的匹配属性这种类型是可以隐式转换的,但我怀疑这将属于“flirting with the bad idea list”领域,无论语言团队是否会讨论它。一般来说,C#在语法上是相当明确的,这会以一种需要两个独立匹配(名称+类型)的方式放松一点,并且在许多情况下都是不明显的。既然你在这里使用公共API(A
),那么在任何一方(A
或任何类型“x”被定义为)的重构都很容易破解这完全是。
最后,这也不是必需的 - 如果你想用这种方式构造A的实例,只需添加一个带有重载的构造函数(在任何情况下都以更多方式更安全),并使用:
repository.GetAll().Select(x=> new A(x.Stuff));
这使得意图和意义非常明确,并且具有脆弱的可维护性。
repository.GetAll().Select(x=> new { x.Stuff });
这是完全不同的事情 - 在这里,您正在初始化一个匿名类型,并让编译器完全确定您的类型名称和类型。我怀疑这被认为是“安全的”,因为你从未真正使用公共API - 匿名类型实际上不应该从它定义的方法中“泄漏”。在这种情况下,重构更改属性名称并有效更改值等的风险会大大降低并隔离到单个方法,从而使这种“自动”命名功能总体上降低了风险。此外,这里没有一个简单的替代方法,因为您无法在匿名类型上定义构造函数,因此在这种情况下,没有一种简单的方法可以使用简洁的语法。这会增加收益而不会带来很多风险。
答案 1 :(得分:1)
一种可能的推理:如果真实类型允许隐式属性赋值而不是存储库项目中的更改(即x.Stuff
重命名为x.Other
)会导致编译时错误,因为新属性非常令人惊讶不再匹配A.Stuff。