C# 规范(团队?委员会?)是否考虑过这种对象创建语法?

发布于 2024-11-03 09:30:31 字数 303 浏览 9 评论 0原文

我以前从未发布过这种性质的问题,所以如果它不适合这样,请不要太伤害我的感情,我会删除它。

为了保留我的一切关心尽可能靠近左边距,我一直希望我可以写这样的东西:

DataService1.DataEntities dataEntities = new(constructorArg1, ...)

我认为另一个原因是我喜欢当类型已经存在于作业的右侧时使用 var 获得的额外屏幕空间,但我的大脑已经寻找了太多年在左侧键入。话又说回来,被困在我的方式中并不是希望有一个规格的好理由......

I've never posted a question of this nature before, so if it's not proper for SO, just don't hurt my feelings too bad and I'll delete it.

In the interest of keeping everything I care about as close to the left margin as possible, I keep wishing I could write something like:

DataService1.DataEntities dataEntities = new(constructorArg1, ...)

I think another reason is I like the extra screen real estate I get by using var when the type is already present on the right side of the assignment, but my brain has too many years of looking for the type on the left side. Then again, being stuck in my ways isn't such a good reason to wish for a spec...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

那支青花 2024-11-10 09:30:31

C# 设计委员会是否考虑过这种对象创建语法?

是的,我们有。几年前我们就考虑过这个问题。作为此主张的证据,请参阅我的文章的最后一段:

http://blogs.msdn.com/b/ericlippert/archive/2009/01/26/why-no-var-on-fields.aspx

设计团队的共识是这是一个“很高兴拥有”的功能,但还不够引人注目,值得花费大量成本来设计、实现、测试、记录和维护该功能。

我还注意到,我链接到的博客文章的评论对该功能非常负面;似乎很多人都觉得这种语法没有吸引力。这也是反对执行该功能的观点。

然而,如果您可以将建议的语法与其他语言功能结合起来,以促进不可变类型的简洁声明,那么它会变得特别好;如果我们在该语言的假设的未来版本中实现这样的功能,那么您提出的语法就会变得更加引人注目。

我进一步指出,我们通常抵制需要从“外部”到“内部”进行推理的功能;我们更喜欢那种由内而外的信息流。例如考虑这个问题:

M(new(blah));

假设 M 有两个重载,一个采用 C,另一个采用 D。这是“new C(blah)”还是“new D(blah)”?也可能是。现在我们必须对两者进行分析!如果它们都有效,那么我们必须找出哪个更好。

情况变得更糟。假设

M(new(new(blah)));

M 再次采用 C 和 D,C 有两个采用 E 或 F 的构造函数,D 有两个采用 G 和 H 的构造函数。

M(new C(new E(blah)));
M(new C(new F(blah)));
M(new D(new G(blah)));
M(new D(new H(blah)));

选择哪一个,为什么?

当您从外向内推理时,您很快就会陷入“组合爆炸”,其中要分析的案例数量在嵌套深度中变为 O(cn)。

C# 以这种方式对 lambda 进行推理,相信我,这是编译器最难提高性能和正确性的部分之一。我们并不急于向构造函数添加类似的功能。如果我们要添加此语法,它可能仅限于通过分析变量声明或赋值表达式的左侧来明确了解类型的场景。

(一如既往,我注意到埃里克对未宣布的、完全虚构的产品中假设的未来语言功能的思考,这些产品没有时间表或预算,仅用于娱乐目的,而不应被解释为对具有任何特定功能的任何特定未来产品的承诺放。)

Has the C# design committee ever considered this object creation syntax?

Yes, we have. We considered it a couple years ago. As evidence of this claim, see the last paragraph of my article here:

http://blogs.msdn.com/b/ericlippert/archive/2009/01/26/why-no-var-on-fields.aspx

The consensus of the design team was that this was a "nice to have" feature but not sufficiently compelling that it was worth the considerable cost of designing, implementing, testing, documenting and maintaining the feature.

I note also that the comments to the blog entry I linked to are very negative about the feature; it seemed like a lot of people found the syntax unattractive. That was also points against doing the feature.

However, the proposed syntax becomes particularly nice if you can combine it with other language features that promote the concise declaration of immutable types; if we do such a feature in a hypothetical future version of the language, then the syntax you propose becomes more compelling.

I note further that we in general resist features that require inference from "outside" to "inside"; we prefer that type information flow from the inside out. Consider for example this problem:

M(new(blah));

Suppose M has two overloads, one that takes a C, and one that takes a D. Is that "new C(blah)" or "new D(blah)"? It could be either. Now we have to analyze both! And if they both work then we have to figure out which is better.

It gets worse. Suppose you have

M(new(new(blah)));

where again M takes a C and a D, and C has two constructors that take an E or an F, and D has two constructors that take an G and an H. Which of:

M(new C(new E(blah)));
M(new C(new F(blah)));
M(new D(new G(blah)));
M(new D(new H(blah)));

is chosen, and why?

When you reason from outside to inside you quickly get into "combinatoric explosions" where the number of cases to analyze becomes O(cn) in the depth of the nesting.

C# does reason in this manner for lambdas and that is one of the hardest parts of the compiler to make performant and correct, believe me. We're not eager to add a similar feature to constructors. If we were to add this syntax it would probably be limited to scenarios in which the type was unambiguously known by analyzing the left hand side of a variable declaration or assignment expression.

(As always, I note that Eric's musings about hypothetical future language features in unannounced and entirely fictional products that do not have schedules or budgets is for entertainment purposes only, and not to be construed as a promise of any particular future product with any particular feature set.)

情深缘浅 2024-11-10 09:30:31

它从左侧向后推断表达式。如果表达式不平凡,它很快就会变得丑陋。

你几乎总是可以通过查看表达式本身来理解表达式的作用(除了一些 lamda 类型推断),而这对于你的语法来说是不可能的。使用 lamda 时,增益相当大,因此复杂的推理对于 lamda 来说是一个很好的权衡,但对于简单的变量初始化来说,为这样一个微不足道的功能增加复杂性是一个糟糕的权衡。

您可以特殊情况“分配给变量,其中右侧最外面的表达式是一个新表达式。”对我来说听起来很不优雅。特别是因为 var 功能已经实现了非常相似的功能,同时更加灵活。

It infers from the left side backwards to the expression. And if the expression is non trivial that gets ugly quite fast.

You can understand what an expression does by just looking at the expression itself almost always(except some lamda type inference), and that isn't possible with your syntax. With lamdas the gain is quite large, so the complicated inference is a good trade-off for lamdas, but adding that complexity for such a trivial feature is a bad trade-off for simple variable initialization.

You could special case "assignment to variable where the outmost expression on the right side is a new expression." Sounds very inelegant to me. Especially since the var feature already achieves something very similar, while being more flexible.

还在原地等你 2024-11-10 09:30:31

如果要创建与用于存储它的成员类型相同的对象,而不必重复类型名称,则可以使用“Stockton new”。缺点是您必须在初始化时重复成员名称。它看起来是这样的:

class Program
    {
       private static T New<T>(out T item) where T : new()
       {
           item = new T();

           return item;
       }

       static Dictionary<Int32, Int32> _member = New(out _member);

       static void Main(string[] args)
       {
           Dictionary<Int32, Int32> local = New(out local);
       }
}

此外,我们可以扩展这个方法,通过几个简单的重载来为相应的接口创建具体的类:

public static IDictionary<TKey, TValue> New<TKey, TValue>(out IDictionary<TKey, TValue> item)
{
     item = new Dictionary<TKey, TValue>();

     return item;
}

public static IList<T> New<T>(out IList<T> item)
{
     item = new List<T>();

     return item;
}

现在你可以这样写:

IDictionary<Int32, Int32> local = New(out local);

一个令人厌恶的东西,一个好奇心,还是一个有用的技术?你决定。

If you want to create an object of the same type as the member used to store it without having to repeat the type name, you can use "Stockton new". The downside is that you have to repeat the member name in the initialization. Here's how it looks:

class Program
    {
       private static T New<T>(out T item) where T : new()
       {
           item = new T();

           return item;
       }

       static Dictionary<Int32, Int32> _member = New(out _member);

       static void Main(string[] args)
       {
           Dictionary<Int32, Int32> local = New(out local);
       }
}

In addition, we can extend this method to create concrete classes for corresponding interfaces with a couple of simple overloads:

public static IDictionary<TKey, TValue> New<TKey, TValue>(out IDictionary<TKey, TValue> item)
{
     item = new Dictionary<TKey, TValue>();

     return item;
}

public static IList<T> New<T>(out IList<T> item)
{
     item = new List<T>();

     return item;
}

Now you can write this:

IDictionary<Int32, Int32> local = New(out local);

An abomination, a curiosity, or a useful technique? You decide.

说不完的你爱 2024-11-10 09:30:31

现在有一个受支持的提案和该功能的精确实现。我们很可能会在 C# 8.0 中看到它。

请参阅 https://github.com/dotnet/csharplang /blob/master/proposals/target-typed-new.md

There is now a championed proposal and an implementation of this feature precisely. We are likely to see it in C# 8.0.

See https://github.com/dotnet/csharplang/blob/master/proposals/target-typed-new.md

甜心小果奶 2024-11-10 09:30:31

不确定,但如果您希望将内容保留在左侧,您可以使用:

var dataEntities = new DataService1.DataEntities(constructorArg1, ...)

Not sure about that but if you are looking to keep things to the left, you could instead use:

var dataEntities = new DataService1.DataEntities(constructorArg1, ...)
撩发小公举 2024-11-10 09:30:31

另外,怎么样:

DataType dt;

意思与: 相同

DataType dt = new DataType();

,然后:

DataType dt = { ParamOne = 1, ParamTwo = 2 };

与: 相同

DataType dt = new DataType(){ ParamOne = 1, ParamTwo =2 };

Also how about having:

DataType dt;

Mean the same as:

DataType dt = new DataType();

And then:

DataType dt = { ParamOne = 1, ParamTwo = 2 };

Is the same as:

DataType dt = new DataType(){ ParamOne = 1, ParamTwo =2 };
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文