C#:如何为部分类中的属性设置默认值?

Posted

技术标签:

【中文标题】C#:如何为部分类中的属性设置默认值?【英文标题】:C#: How to set default value for a property in a partial class? 【发布时间】:2009-08-13 15:12:31 【问题描述】:

我对 C# 很陌生,所以请多多包涵……

我正在实现一个部分类,并想添加两个属性,如下所示:

public partial class SomeModel

    public bool IsSomething  get; set; 
    public List<string> SomeList  get; set; 

    ... Additional methods using the above data members ...

我想初始化两个数据成员:IsSomethingTrueSomeListnew List&lt;string&gt;()。通常我会在构造函数中执行它,但是因为它是一个部分类,我不想接触构造函数(应该吗?)。

实现这一目标的最佳方法是什么?

谢谢

PS 我在 ASP.NET MVC 中工作,为某个模型添加功能,因此是部分类。

【问题讨论】:

这些已经是这些类型的默认值。你不需要做任何事情。 我想明确。如果我想要“True”或“new List()”怎么办? 我编辑了问题以反映不是“自然”默认值的值。 您必须使用后备存储字段,并内联初始化它,或者将其放入构造函数中。 @John:你不需要做任何事情——只要你希望你的调用者/客户为你初始化 SomeList 属性;) 【参考方案1】:

针对 C# 6 更新

C# 6 添加了为自动属性分配默认值的功能。该值可以是任何表达式(不必是常量)。举几个例子:

// Initialize to a string literal
public string SomeProperty get;set; = "This is the default value";

// Initialize with a simple expression
public DateTime ConstructedAt get; = DateTime.Now;

// Initialize with a conditional expression
public bool IsFoo  get;  = SomeClass.SomeProperty ? true : false;

原答案

可以在类构造函数中初始化自动实现的属性,但不能在属性本身上初始化。

public SomeModel

    IsSomething = false;
    SomeList = new List<string>();

...或者您可以使用字段支持的属性(稍微多一点工作)并初始化字段本身...

private bool _IsSomething = false;
public bool IsSomething

    get  return _IsSomething; 
    set  _IsSomething = value; 

更新:我上面的回答并没有说明这是在一个部分类中的问题。 Mehrdad's answer 提供了使用部分方法的解决方案,这符合我的第一个建议。我的第二个建议是使用非自动实现的属性(手动实现的属性?)将适用于这种情况。

【讨论】:

SomeList = new List**()**; 关于您的第一个建议,这样做是否被视为“良好做法”?这肯定会更容易,但感觉就像“代码味道”...... @RaxL 我对它的气味持怀疑态度。初始化逻辑是 OO 开发中相当正常的一部分;如果在系统上工作的开发人员遵循相同的做法,那么我不认为这将是一个问题。 请注意这一点,在您的自动生成的类中添加任何代码(包括此答案)都将在刷新模型后消失。 @H35am 你永远不应该修改生成的类(脚手架是另一回事——你永远不会“刷新”或重新生成脚手架)【参考方案2】:

第一个属性 (IsSomething) 是一个布尔值。默认为 false。

第二个属性,因为它是一个引用类型,将默认为 null,而无需您做任何努力。您无需触及构造函数,因为引用类型(类)在 .NET 中会自动以 null 开始。

如果您想使用非默认值,您有两个选择 -

首先,使用后备存储字段:

private bool isSomething = true;
public bool IsSomething 
    get  return this.isSomething; 
    set  this.isSomething = value; 

第二个选项 - 将其添加到构造函数中。

请注意,第一个选项没有额外的开销 - 它基本上是编译器在您使用自动属性时所做的。

【讨论】:

+1 用于指出值/引用类型的不同行为。【参考方案3】:

你不能在分部类的两个部分中有两个构造函数。但是,您可以使用partial methods 来完成类似的操作:

// file1:
partial void Initialize();
public Constructor() 
    // ... stuff ... initialize part 1
    Initialize();


// file2:
void Initalize() 
    // ... further initializations part 2 might want to do

如果分部类的任何部分都没有定义分部方法,那么对它的所有调用都将被省略。

【讨论】:

唉,如果类中具有构造函数的部分是生成代码,这将无济于事。【参考方案4】:

WCF 部分类用户的警告

如果您尝试将属性添加到 WCF 代理类(由添加服务引用生成),您可能会惊讶地发现私有字段未初始化,因为显然 no constructor at all is called。

如果您尝试这样做(如其他答案中所建议的那样),它将永远不会被调用:

    private bool _sendEmail = true;

这与该字段是否属于部分类无关。

您需要做的是添加一个[OnDeserialized] 属性,它可以让您对对象进行进一步的初始化。这是 System.Runtime.Serialization 的一部分,因此仅在使用 DataContractSerializer 时在序列化上下文中有用。

public partial class EndOfDayPackageInfo

    [OnDeserialized()]
    public void Init(StreamingContext context)
    
        _sendEmail = true;
    

    private bool _sendEmail;
    public bool SendEmail
    
        get
        
            return _sendEmail;
        
        set
        
            _sendEmail = value;
            RaisePropertyChanged("SendEmail");
        
    

另一种方法是“延迟加载”属性 - 但这种方法不太优雅。

    private bool _sendEmail;
    private bool _sendEmailInitialized;

    public bool SendEmail
    
        get
        
            if (!_sendEmailInitialized)
            
                _sendEmailInitialized = true;
                _sendEmail = true;  // default value
            

            return _sendEmail;
        
        set
        
            if (!_sendEmailInitialized)
            
                // prevent unwanted initialization if 'set' is called before 'get'
                _sendEmailInitialized = true;
            

            _sendEmail = value;
            RaisePropertyChanged("SendEmail");
        
    

【讨论】:

多么有趣。以一种扭曲的方式有意义。 是的,但起初很混乱。今天才发现这个,并认为这是一个 WPF 绑定问题,直到我终于意识到它是 WCF。原来他们调用这个方法来绕过调用任何构造函数:msdn.microsoft.com/en-us/library/… 谢谢,这正是我的问题。 什么是 RaisePropertyChange 方法?这个方法是来自.net框架吗??【参考方案5】:

对此,不要使用自动属性,而是使用旧方式

YourType _yourParameter = yourDefaultValue;
public YourType YourParameter

   getreturn _yourParameter;
   set_yourParameter=value;

【讨论】:

【参考方案6】:

对于 C# 6.0 版本的用户,可以像这样初始化属性:

public bool IsSomething  get; set;  = true;
public List<string> SomeList  get; set;  = new List<string>();

【讨论】:

【参考方案7】:

您的两个属性都已经具有您需要的默认值。

在部分类中使用构造函数并没有错。分部类并没有什么特别之处,除了它们的源代码分布在多个文件/声明中。

【讨论】:

正如 Reed 在他的评论中指出的,值类型将使用默认值初始化(0 表示 int,false 表示 bool...),但引用类型将初始化为 null/Nothing。所以在他的情况下 IsSomething = false 和 SomeList = null @Yooder:当问题仍然要求默认值为 False 和 null 时,提供了此答案。请收回你的 -1,这对@Programming Hero 不公平 在比赛中途移动球门柱?不公平!【参考方案8】:
 private bool _InternalUserContactUpdate = false;
        public bool InternalUserContactUpdate
        
            get  return _InternalUserContactUpdate; 
            set  _InternalUserContactUpdate = value; 
        

那么当你想覆盖条件上的值时,

if(!objUserModel.FirstName.ToLower().Equals(entry.Key[0].Attributes.Contains("firstname").ToString().ToLower()))
        
             objUserModel.InternalUserContactUpdate= true;
        

希望这会有所帮助

【讨论】:

以上是关于C#:如何为部分类中的属性设置默认值?的主要内容,如果未能解决你的问题,请参考以下文章

代码优先迁移:如何为新属性设置默认值?

如何为 Laravel / Eloquent 模型设置默认属性值?

如何为整个 c# 应用程序设置默认文化信息

更新CoreData模型版本时如何为实体的新属性设置默认值

Rails:如何为 Rails activerecord 模型中的属性创建默认值? [复制]

如何为 kendo ui 下拉菜单设置默认值?