对象初始化程序强制编译错误

时间:2012-03-29 01:09:08

标签: c# object initialization compiler-warnings initializer

在C#中使用对象初始值设定项时是否可以强制执行规则或抛出错误?如果对象已初始化但缺少某个属性,我想抛出编译器错误或警告。

public class Party
{
    public string Name { get; set; }
    public string Date { get; set; }
    public Location Location { get; set; }
}

public class SignUpForParty
{
    public void DoSomething()
    {
        Party party = new Party()
        {
            Name = "New Years Party!",
            Date = "Dec 31, 1999"
            // Show WARNING/ERROR here because no Location given
        };
    }
}

基本上,我正在寻找一种方法来确保使用每个实例的有效数据创建Party类型的所有对象。

显然我可以用重载的构造函数来做这件事,但在某些情况下我有很多属性,编写构造函数来匹配是混乱的。我想要采用更清洁的C#风格。

Obj p = new Obj(1, 2, 3,...n); // too many properties to be pretty

5 个答案:

答案 0 :(得分:4)

  

显然我可以用重载的构造函数来做这件事,但在某些情况下我有很多属性,编写构造函数来匹配是混乱的。我想要采用更清洁的C#风格。

对象初始值设定项实际上不应被视为编写构造函数的替代方法。

如果您有类似的要求,则应始终在类型中包含构造函数。创建一组默认构造函数(或在一个构造函数上使用可选参数)是一个好主意,这至少可以保证对象始终以有效,有意义的状态创建。

对象初始值设定项对可选属性有帮助,但不应依赖于类型本身的要求。

答案 1 :(得分:3)

您不能强制使用对象初始值设定项初始化每个属性。

即使你可以,该对象的使用者也可以提供默认值(0,null,...)。根据您的需要,考虑在关键时刻验证对象状态(例如,在将其保存到数据库之前)。

如果您走这条路线,请查看IDataErrorInfo界面。

答案 2 :(得分:2)

如果只设置了2个属性时类型无效,则需要修改设计,而不是发出错误。

你提供了一个默认的构造函数,它告诉我在初始化之后我不需要设置任何东西来使用该对象。您为每个属性提供getter和setter,再次隐式告诉您的类的用户可以设置而不是另一个。

如果不是这种情况,那么我建议你提供一个强制我提供所有三个值的构造函数。是的,我仍然可以使用(null, null, null),但您可以检查并发出错误。

此外,如果PropertyA依赖于PropertyB,则

A)其中只有一个应该有一个二传手,或

B)每个设置器中都应该有逻辑,以便在值更改后正确初始化另一个。

这是设计问题,而不是语言问题。您无法强制初始化程序语法的工作方式与规范的方式不同。

  

Obj p = new Obj(1,2,3,... n); //太多的属性非常漂亮

代码不应该是“漂亮的”,它应该可行。即便如此,一个带有一些参数的构造函数是“丑陋的”?咦?不要购买时髦的废话,写出有效的代码。

答案 3 :(得分:0)

我能看到这个实现的唯一方法是,如果在对象初始化程序完成时引发了某些事件(或等效的)。目前有Connect request这样的效果。

不幸的是,我没有为.NET 4.5做好准备:

  

感谢您的建议。

     

这是一个好主意,并且具有不会添加到语言表面的良好属性 - 它只是使对象初始化器更加智能。原则上这可能会使它成为一个突破性的变化,但这是我们可以研究的内容。

     

不幸的是我们不能再添加到我们当前正在构建的版本中,所以我将解决因为无法修复此版本。但是,我正在捕获我们的功能列表中的建议,以供将来讨论。

     

再次感谢!

     

Mads Torgersen,C#语言PM

也许它会进入.NET 5 +。

答案 4 :(得分:0)

Code Contracts怎么样?这将断言您不仅指定了一个值,还可以指定有效范围。

或者仅在运行时使用调试版本进行检查,您可以使用Debug.Assert(...)调用来实现与上述相同。