c#规范团队?)是否考虑过这个对象创建语法

本文关键字:考虑过 对象 语法 创建 是否 范团队 团队 | 更新日期: 2023-09-27 17:52:45

我以前从来没有发过这种性质的问题,所以如果它不适合so,只是不要太伤害我的感情,我会删除它

为了让所有我关心的东西尽可能靠近左边的空白处,我一直希望我能写这样的东西:

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

我认为另一个原因是,当类型已经出现在分配的右侧时,我喜欢使用var获得的额外屏幕空间,但是我的大脑已经在左侧寻找类型很多年了。然而,被困在我的生活方式中并不是一个希望得到规范的好理由……

c#规范团队?)是否考虑过这个对象创建语法

c#设计委员会考虑过这个对象创建语法吗?

是的,有。我们几年前就考虑过了。作为这种说法的证据,请参阅我文章的最后一段:

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

设计团队的共识是,这是一个"有就好"的特性,但不够引人注目,不足以值得为设计、实现、测试、记录和维护该特性付出可观的成本。

我还注意到,我所链接的博客条目的评论对该功能非常负面;似乎很多人都觉得这种语法没有吸引力。这也是反对做这个功能的原因。

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

我进一步注意到,我们通常抵制需要从"外部"推断到"内部"的特征;我们更喜欢由内而外的信息流。例如考虑这个问题:

M(new(blah));

假设M有两个重载,一个接受C,另一个接受D,是"新C(废话)"还是"新D(废话)"?两者都有可能。现在我们要分析两者!如果两者都适用,那么我们必须找出哪个更好。

情况更糟。假设你有

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#确实以这种方式对lambdas进行推理,这是编译器中最难实现性能和正确性的部分之一,相信我。我们并不急于在构造函数中添加类似的功能。如果我们要添加这种语法,它可能仅限于通过分析变量声明或赋值表达式的左侧来明确地知道类型的场景。

(像往常一样,我注意到Eric对未公布的、完全虚构的、没有时间表或预算的产品中假设的未来语言功能的思考只是为了娱乐目的,而不是被解释为对任何特定未来产品的任何特定功能集的承诺。)

它从左边向后推断到表达式。如果表达式是非平凡的,那么它很快就会变得很难看。

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

您可以在特殊情况下"对右边最外面的表达式是new表达式的变量赋值"。听起来很不优雅。特别是因为var特性已经实现了非常相似的功能,同时更加灵活。

如果您希望创建与用于存储它的成员类型相同的对象,而不必重复类型名称,则可以使用"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);

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

现在有一个被支持的提案和这个特性的实现。我们可能会在c# 8.0中看到它。

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

不确定,但如果你想保持东西在左边,你可以使用:

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

还有:

DataType dt;

的意思与

相同
DataType dt = new DataType();

然后:

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

等于:

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