为什么要使用初始化器?(.net)

5
我有这个:
AudioPlayer player = new AudioPlayer();
player.Directory = vc.Directory;
player.StartTime = vc.StarTime;
player.EndTime = vc.EndTime;

但我可以拥有这个:
AudioPlayer player = new AudioPlayer
{
    Directory = vc.Directory,
    StartTime = vc.StarTime,
    EndTime = vc.EndTime
};

如果我转换到“新的写作方式”,除了难以阅读之外,我能获得什么?这会让我更接近lambda函数(=>)吗?
这与RAII有关吗?
补充:
有些人回答说,正常初始化可能会在仅设置目录属性之后将对象留在“无效”状态 - 我的观察是,设计对象的人可能以只有真正必须输入的值通过真正的构造函数输入,而所有其他值稍后可以自由修改的方式来设计它。

嗯,看起来我的关于lambda表达式的直觉是正确的! - Daniel Mošmondor
请查看您最喜欢的C#语言书籍,了解“匿名类型”。 - Hans Passant
@Hans:是指“临时属性容器”吗? - Daniel Mošmondor
不确定这是什么意思。链接:http://msdn.microsoft.com/zh-cn/library/bb397696.aspx - Hans Passant
我的意思是,每次需要一些属性的容器时都不必声明一个类 - 匿名方法来拯救。 - Daniel Mošmondor
6个回答

10

仅凭这样一个简单的示例,你确实不会获得太多东西。但当你拥有这个时,情况就不同了:

var player = new AudioPlayer
{
    Car = new Car()
    {
        WheelSize = new Inch(21),
        Driver = new Person()
        {
            Age = 53,
            Type = LicenseType.B,
            Family =
            {
                new Person("Jane"),
                new Person("Pieter"),
                new Person("Anny")
            }
        }
    }
    Directory = vc.Directory,
    StartTime = vc.StarTime,
    EndTime = vc.EndTime
};

尝试用旧的方法去做,这会变得非常丑陋。


一个微不足道的点,但在调用无参构造函数时括号是不必要的。 - Ani
@Ani:这就是为什么 new AudioPlayer 没有括号的原因 :-) - Steven

2

假设您想将新创建的对象传递给某个方法(而不做其他任何操作)。 您可以按照旧方式编写:

AudioPlayer player = new AudioPlayer();
player.Directory = vc.Directory;
player.StartTime = vc.StarTime;
player.EndTime = vc.EndTime;
some.Method(player);

或者你可以使用对象初始化器:

some.Method(
  new AudioPlayer
  {
      Directory = vc.Directory,
      StartTime = vc.StarTime,
      EndTime = vc.EndTime
  });

使用对象初始化程序,您可以清楚地看到代码的作用,以及该对象后面未被使用。
另外,我认为可读性(和“可写性”)更好:您不必无休止地重复变量名称。

好了,VB6中的'with'关键字来了! :) - Daniel Mošmondor

2
您不仅会失去可读性,还会因为将对象放入无效状态而增加引起错误的能力。这与RAII唯一相关的事情是RAII依赖于合理的不变量,而初始化程序很容易破坏不变量。然而,在创建匿名值或创建普通数据风格的对象(其中类是值和不变量的“愚蠢”容器,不变量并不重要)方面,它可能非常有用。这对于lambda函数和linq表达式特别有用,但它们既不是必需的,也不限于它们。当一个类维护一个不变量时,以这种方式初始化它不是一个好主意,而且从一个接受值的构造函数重写到新语法的规则是一个坏主意。在您的示例中,第一种情况没有使用其构造函数将其初始化为保证有效状态。这是一个坏味道(在拥有目录、开始时间和结束时间之前,玩家应该做什么?),但当一个给定的类合理时,使用新语法也是可以的。新语法可以在单个表达式中设置对象,这个表达式又可以成为另一个表达式的一部分,这就是它可能有用的地方,是的,这也包括在lambda表达式中。

2

当处理匿名类型时,初始化程序不仅仅是有用的,而且是必需的。

例如:

var x = new { Foo = "foo", Bar = "bar" };


这个特定实例,它是否与 .net 2.0 兼容?即,它是 IDE、编译器还是 .net 运行时的一个特性? - Daniel Mošmondor

1

我相信这个语法是为了更容易与lambda表达式一起使用而添加的,所以你可以轻松地做一些像item => new Person() { Name = item.Name }这样的事情。

我不认为它与RAII有任何关系..


1

你可以减少21个字符的代码。更少的代码意味着更少的错误。为了获得更多的优势,你可以使用隐式变量类型推断:var player = new AudioPlayer {


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接