C# 构造函数

12

请问有人能给我建议,在写C#构造函数时应该采取哪种方法?

在其他语言中,如C++,一切都很好-通常您不会使内部字段可见,并为它们提供getter / setter。

这意味着您可以使用构造函数为类初始化所有/某些本地成员,并感到满意。


C#属性,这使我们可以编写以下内容:

Class x = new Class { Field1 = new Field1 ...., Field2 = new Field2 }

这样可以使对象构建变得更加容易,并且可以省去很多必需的构造函数,如果没有属性的话就需要它们。

结合使用属性的默认值,我们可以完全摆脱一些实际有用的非专业化构造函数。

现在,删除冗余构造函数并通过字段初始化允许对象构造是否可行?

这种方法有什么缺点?能否给出关于组合使用字段和构造函数的一般建议,或者一些经验法则吗?

谢谢。


http://www.yoda.arachsys.com/csharp/constructors.html - Mitch Wheat
那些不是字段,它们是属性。 - Femaref
其他编程语言(尤其是C++)也有字段。在您的示例中,“Field1”是一个属性。 - H H
9个回答

16

我的经验法则很简单:如果某个东西是构建对象所必需的,那么它应该是一个构造函数参数。

StreamReader或BinaryReader这样的Stream助手对象就是一个很好的例子。它们无法在没有关联的Stream对象的情况下运行,因此必须在构造函数中指定。


6

在我看来,拥有所谓的冗余构造函数并没有什么问题。如果你想定义一个构造函数,那很可能是因为有一种真正需要以那种方式实现的情况。


4
构造函数可以用来强制消费者向类提供值。
我的经验法则是,字段用于可选数据,而构造函数可用于强制要求的数据。
然而,这个问题有点虚假的二分法。C++的行为与C#相同 - “字段”(实际上是属性 - 字段是类级变量)通常用作获取器/设置器以设置内部值,而允许您设置字段的new语法只是一种简写形式。
Class x = new Class();
x.Field1 = new Field1();
x.Field2 = new Field2();

2

最佳实践是创建一个可用状态的对象;尽量减少对属性设置器的依赖。

这可以减少创建不完整对象的机会,从而使代码更加健壮。


2
你发布的代码正在使用所谓的对象初始化程序,这只是一种最近引入的语法糖。使用对象初始化程序只是一种调用构造函数并设置属性的简写方式。在C#中应该继续像在其他语言中使用构造函数的方式--通常规则是如果一个类需要一个对象或值来正确初始化,那么参数应该通过构造函数传递。如果该值不是必需的,则将其作为可设置属性也是合理的。
一般来说,我尽可能避免使用setter(当然有很多情况下无法避免)。

1

对象初始化器语法只是一种语法糖。即使在 C# 1 中,您也可以编写

Class c = new Class();
c.Property1 = value1;
c.Property2 = value2;
c.Property3 = value3;
....

C# 3基本上缩短了语法:

Class c = new Class 
{
   Property1 = value1, 
   Property2 = value2, 
   Property3 = value3
   ....
}

构造函数的目的不仅仅是设置字段,它应该根据参数逻辑地构造对象,以便在构造函数返回时,你得到的是一个可以直接使用的对象。

1

公共参数初始化构造方法是一种常见的方法,通常用于XAML中,很多WPF工具都在使用。

唯一的问题是你可能会遇到部分初始化的对象,但你可以在使用字段前简单地验证对象状态。

个人而言,我会将关键值作为构造函数的参数,在一个对象拷贝和一系列可选参数的基础上建立副本构造函数,但我还没有制作出需要由XAML消费的东西。


我认为原问题并不是关于可选参数,而是关于对象初始化程序。然而,可选参数在这里当然是另一种选择! - Steve
它属于摆脱专用构造函数的点,但确实没有直接提到。这让我的答案略有不同 :-) - Adam Houldsworth

0

可以吗?那要看情况而定...

为了使用对象初始化程序,您需要将所有字段公开设置器,您可能不想这样做。如果您愿意公开它们,那么我会建议您继续删除构造函数。然而,仅仅因为您可以做某事并不意味着您应该这样做。我认为只有在发现所有字段都是可公开设置的情况下,才应该删除构造函数,不要使字段可设置只是为了允许您删除构造函数。


0

我怀疑你在这里提到的是领域对象,但是对于服务来说,通过构造函数注入服务的依赖使得服务更加自描述,而不是使用"new"关键字创建依赖项。此外,这也让你更容易使用依赖注入容器。


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