给 C# 自动属性一个初始值的最佳方法是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/40730/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the best way to give a C# auto-property an initial value?
提问by bentford
How do you give a C# auto-property an initial value?
你如何给 C# 自动属性一个初始值?
I either use the constructor, or revert to the old syntax.
我要么使用构造函数,要么恢复到旧语法。
Using the Constructor:
使用构造函数:
class Person
{
public Person()
{
Name = "Initial Name";
}
public string Name { get; set; }
}
Using normal property syntax(with an initial value)
使用普通属性语法(带有初始值)
private string name = "Initial Name";
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
Is there a better way?
有没有更好的办法?
采纳答案by Darren Kopp
In C# 5 and earlier, to give auto implemented properties an initial value, you have to do it in a constructor.
在 C# 5 及更早版本中,要为自动实现的属性提供初始值,您必须在构造函数中执行此操作。
Since C# 6.0, you can specify initial value in-line. The syntax is:
从 C# 6.0 开始,您可以内联指定初始值。语法是:
public int X { get; set; } = x; // C# 6 or higher
DefaultValueAttribute
is intended to be used by the VS designer (or any other consumer) to specify a default value, not an initial value. (Even if in designed object, initial value is the default value).
DefaultValueAttribute
旨在供 VS 设计者(或任何其他使用者)用于指定默认值,而不是初始值。(即使在设计对象中,初始值也是默认值)。
At compile time DefaultValueAttribute
will not impact the generated IL and it will not be read to initialize the property to that value (see DefaultValue attribute is not working with my Auto Property).
在编译时DefaultValueAttribute
不会影响生成的 IL 并且不会读取它以将属性初始化为该值(请参阅DefaultValue 属性不适用于我的 Auto Property)。
Example of attributes that impact the IL are ThreadStaticAttribute
, CallerMemberNameAttribute
, ...
影响 IL 的属性示例是ThreadStaticAttribute
, CallerMemberNameAttribute
, ...
回答by OwenP
Have you tried using the DefaultValueAttributeor ShouldSerialize and Reset methodsin conjunction with the constructor? I feel like one of these two methods is necessary if you're making a class that might show up on the designer surface or in a property grid.
您是否尝试过将DefaultValueAttribute或ShouldSerialize 和 Reset 方法与构造函数结合使用?如果您正在制作一个可能出现在设计器表面或属性网格中的类,我觉得这两种方法中的一种是必要的。
回答by crucible
Sometimes I use this, if I don't want it to be actually set and persisted in my db:
有时我会使用它,如果我不希望它被实际设置并保留在我的数据库中:
class Person
{
private string _name;
public string Name
{
get
{
return string.IsNullOrEmpty(_name) ? "Default Name" : _name;
}
set { _name = value; }
}
}
Obviously if it's not a string then I might make the object nullable ( double?, int? ) and check if it's null, return a default, or return the value it's set to.
显然,如果它不是字符串,那么我可能会将该对象设为可空( double?, int? )并检查它是否为 null、返回默认值或返回其设置的值。
Then I can make a check in my repository to see if it's my default and not persist, or make a backdoor check in to see the true status of the backing value, before saving.
然后我可以在我的存储库中检查它是否是我的默认值而不是持久化,或者在保存之前进行后门检查以查看支持值的真实状态。
Hope that helps!
希望有帮助!
回答by Joel Coehoorn
Personally, I don't see the point of making it a property at all if you're not going to do anything at all beyond the auto-property. Just leave it as a field. The encapsulation benefit for these item are just red herrings, because there's nothing behind them to encapsulate. If you ever need to change the underlying implementation you're still free to refactor them as properties without breaking any dependent code.
就个人而言,如果您不打算做任何超出自动财产的事情,我根本看不出将其作为财产的意义。把它作为一个领域。这些项目的封装好处只是红鲱鱼,因为它们背后没有任何东西可以封装。如果您需要更改底层实现,您仍然可以自由地将它们重构为属性,而不会破坏任何相关代码。
Hmm... maybe this will be the subject of it's own question later
嗯......也许这将是稍后自己问题的主题
回答by Keith
When you inline an initial value for a variable it will be done implicitly in the constructor anyway.
当您内联变量的初始值时,它无论如何都会在构造函数中隐式完成。
I would argue that this syntax was best practice in C# up to 5:
我认为这种语法是 C# 中的最佳实践,最多 5 个:
class Person
{
public Person()
{
//do anything before variable assignment
//assign initial values
Name = "Default Name";
//do anything after variable assignment
}
public string Name { get; set; }
}
As this gives you clear control of the order values are assigned.
因为这使您可以清楚地控制分配的订单值。
As of C#6 there is a new way:
从 C#6 开始,有一种新方法:
public string Name { get; set; } = "Default Name";
回答by Lex
In C# 6 and above you can simply use the syntax:
在 C# 6 及更高版本中,您可以简单地使用以下语法:
public object Foo { get; set; } = bar;
Note that to have a readonly
property simply omit the set, as so:
请注意,要拥有readonly
属性只需省略集合,如下所示:
public object Foo { get; } = bar;
You can also assign readonly
auto-properties from the constructor.
您还可以readonly
从构造函数分配自动属性。
Prior to this I responded as below.
在此之前,我回应如下。
I'd avoid adding a default to the constructor; leave that for dynamic assignments and avoid having two points at which the variable is assigned (i.e. the type default and in the constructor). Typically I'd simply write a normal property in such cases.
我会避免向构造函数添加默认值;将其留给动态赋值并避免变量被赋值的两个点(即类型默认值和构造函数中)。通常我会在这种情况下简单地编写一个普通的属性。
One other option is to do what ASP.Net does and define defaults via an attribute:
另一种选择是做 ASP.Net 所做的事情并通过属性定义默认值:
http://msdn.microsoft.com/en-us/library/system.componentmodel.defaultvalueattribute.aspx
http://msdn.microsoft.com/en-us/library/system.componentmodel.defaultvalueattribute.aspx
回答by ghiboz
little complete sample:
小完整样本:
using System.ComponentModel;
private bool bShowGroup ;
[Description("Show the group table"), Category("Sea"),DefaultValue(true)]
public bool ShowGroup
{
get { return bShowGroup; }
set { bShowGroup = value; }
}
回答by Nag
class Person
{
/// Gets/sets a value indicating whether auto
/// save of review layer is enabled or not
[System.ComponentModel.DefaultValue(true)]
public bool AutoSaveReviewLayer { get; set; }
}
回答by Chuck Rostance
Edited on 1/2/15
15 年 1 月 2 日编辑
C# 6:
C# 6:
With C# 6 you can initialize auto-properties directly (finally!), there are now other answers in the thread that describe that.
使用 C# 6,您可以直接初始化自动属性(终于!),现在该线程中有其他答案描述了这一点。
C# 5 and below:
C# 5 及以下:
Though the intended use of the attribute is not to actually set the values of the properties, you can use reflection to always set them anyway...
虽然属性的预期用途不是实际设置属性的值,但您可以使用反射来始终设置它们......
public class DefaultValuesTest
{
public DefaultValuesTest()
{
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(this))
{
DefaultValueAttribute myAttribute = (DefaultValueAttribute)property.Attributes[typeof(DefaultValueAttribute)];
if (myAttribute != null)
{
property.SetValue(this, myAttribute.Value);
}
}
}
public void DoTest()
{
var db = DefaultValueBool;
var ds = DefaultValueString;
var di = DefaultValueInt;
}
[System.ComponentModel.DefaultValue(true)]
public bool DefaultValueBool { get; set; }
[System.ComponentModel.DefaultValue("Good")]
public string DefaultValueString { get; set; }
[System.ComponentModel.DefaultValue(27)]
public int DefaultValueInt { get; set; }
}
回答by Zack Jannsen
To clarify, yes, you need to set default values in the constructor for class derived objects. You will need to ensure the constructor exists with the proper access modifier for construction where used. If the object is not instantiated, e.g. it has no constructor (e.g. static methods) then the default value can be set by the field. The reasoning here is that the object itself will be created only once and you do not instantiate it.
为了澄清,是的,您需要在类派生对象的构造函数中设置默认值。您将需要确保构造函数存在,并且在使用的构造中具有正确的访问修饰符。如果对象未实例化,例如它没有构造函数(例如静态方法),则可以通过字段设置默认值。这里的推理是对象本身只会被创建一次并且您不会实例化它。
@Darren Kopp - good answer, clean, and correct. And to reiterate, you CAN write constructors for Abstract methods. You just need to access them from the base class when writing the constructor:
@Darren Kopp - 很好的答案,干净,正确。重申一下,您可以为抽象方法编写构造函数。您只需要在编写构造函数时从基类访问它们:
Constructor at Base Class:
基类的构造函数:
public BaseClassAbstract()
{
this.PropertyName = "Default Name";
}
Constructor at Derived / Concrete / Sub-Class:
派生/混凝土/子类的构造函数:
public SubClass() : base() { }
The point here is that the instance variable drawn from the base class may bury your base field name. Setting the current instantiated object value using "this." will allow you to correctly form your object with respect to the current instance and required permission levels (access modifiers) where you are instantiating it.
这里的重点是从基类中提取的实例变量可能会掩盖您的基字段名称。使用“this”设置当前实例化的对象值。将允许您根据当前实例和实例化它的所需权限级别(访问修饰符)正确形成您的对象。