Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 给C auto属性一个初始值的最佳方法是什么?_C#_Constructor_Getter_Setter_Automatic Properties - Fatal编程技术网

C# 给C auto属性一个初始值的最佳方法是什么?

C# 给C auto属性一个初始值的最佳方法是什么?,c#,constructor,getter,setter,automatic-properties,C#,Constructor,Getter,Setter,Automatic Properties,如何给C auto属性一个初始值 我要么使用构造函数,要么恢复到旧语法 使用构造函数: 对初始值使用普通属性语法 private string name = "Initial Name"; public string Name { get { return name; } set { name = value; } } 有更好的方法吗?您是否尝试过将or与构造函数结合使用?我觉得,如果要创建一个可能出现在设计器

如何给C auto属性一个初始值

我要么使用构造函数,要么恢复到旧语法

使用构造函数:

对初始值使用普通属性语法

private string name = "Initial Name";
public string Name 
{
    get 
    {
        return name;
    }
    set
    {
        name = value;
    }
}

有更好的方法吗?

您是否尝试过将or与构造函数结合使用?我觉得,如果要创建一个可能出现在设计器界面或属性网格中的类,则必须使用这两种方法之一。

在C 5及更早版本中,要为自动实现的属性提供初始值,必须在构造函数中执行

从C6.0开始,您可以在线指定初始值。语法是:

public int X { get; set; } = x; // C# 6 or higher
用于VS设计器或任何其他使用者指定默认值,而不是初始值。即使在设计对象中,初始值也是默认值

在编译时,DefaultValueAttribute不会影响生成的IL,并且不会读取它以将属性初始化为该值。请参阅


影响IL的属性示例是,…

如果我不想在我的数据库中实际设置和持久化,有时我会使用此属性:

class Person
{
    private string _name; 
    public string Name 
    { 
        get 
        {
            return string.IsNullOrEmpty(_name) ? "Default Name" : _name;
        } 

        set { _name = value; } 
    }
}
显然,如果它不是一个字符串,那么我可能会将对象设置为可为null的double?,int?并检查它是否为null,返回默认值,或返回它设置的值

然后,在保存之前,我可以在存储库中进行检查,以查看它是否为默认值且不持久,或者进行后门检入以查看支持值的真实状态


希望有帮助

就我个人而言,如果你不打算在汽车产业之外做任何事情,我根本不认为把它变成一个产业有什么意义。把它当作一块地就行了。这些项目的封装好处只是转移注意力,因为它们背后没有什么可封装的东西。如果您需要更改底层实现,您仍然可以自由地将它们重构为属性,而不会破坏任何依赖代码


嗯。。。这可能是以后它自己的问题

当您为变量内联一个初始值时,它将在构造函数中隐式完成

我认为这种语法是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; }
}
因为这使您可以清楚地控制分配的顺序值

从C6开始,有一种新的方式:

public string Name { get; set; } = "Default Name";

在C 6及以上版本中,您只需使用以下语法:

public object Foo { get; set; } = bar;
请注意,要拥有只读属性,只需省略集合,如下所示:

public object Foo { get; } = bar;
还可以从构造函数中指定只读自动属性

在此之前,我的回答如下

我会避免在构造函数中添加默认值;将其保留为动态赋值,并避免在变量赋值的两个点上,即默认类型和构造函数中。在这种情况下,我通常只编写一个普通属性

另一个选项是执行ASP.Net的操作,并通过属性定义默认值:


小样本:

using System.ComponentModel;

private bool bShowGroup ;
[Description("Show the group table"), Category("Sea"),DefaultValue(true)]
public bool ShowGroup
{
    get { return bShowGroup; }
    set { bShowGroup = value; }
}
2015年1月2日编辑

C 6:

使用C 6,您最终可以直接初始化自动属性!,现在有其他的答案描述了这一点

C 5及以下:

虽然属性的预期用途不是实际设置属性的值,但您可以使用反射始终设置它们

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; }
}

要澄清,是的,您需要在构造函数中为类派生对象设置默认值。您将需要确保构造函数在使用时具有适当的访问修饰符。如果对象未实例化,例如没有构造函数(例如静态方法),则可以通过字段设置默认值。这里的理由是对象本身只会被创建一次,而您不会实例化它

@Darren Kopp-回答正确、干净、正确。重申一下,您可以为抽象方法编写构造函数。编写构造函数时,只需从基类访问它们:

基类上的构造函数:

public BaseClassAbstract()
{
    this.PropertyName = "Default Name";
}
派生/混凝土/子类的建造商:

public SubClass() : base() { }

这里的要点是,从基类中提取的实例变量可能会隐藏基本字段名。使用此设置当前实例化的对象值。将允许您根据当前实例和所需的权限级别正确形成对象,并在实例化对象时访问修改器。

我的解决方案是使用自定义属性,通过常量或使用属性类型初始值设定项提供默认值属性初始化

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class InstanceAttribute : Attribute
{
    public bool IsConstructorCall { get; private set; }
    public object[] Values { get; private set; }
    public InstanceAttribute() : this(true) { }
    public InstanceAttribute(object value) : this(false, value) { }
    public InstanceAttribute(bool isConstructorCall, params object[] values)
    {
        IsConstructorCall = isConstructorCall;
        Values = values ?? new object[0];
    }
}
要使用此属性,必须从特殊的基类初始值设定项继承类或使用静态帮助器方法:

public abstract class DefaultValueInitializer
{
    protected DefaultValueInitializer()
    {
        InitializeDefaultValues(this);
    }

    public static void InitializeDefaultValues(object obj)
    {
        var props = from prop in obj.GetType().GetProperties()
                    let attrs = prop.GetCustomAttributes(typeof(InstanceAttribute), false)
                    where attrs.Any()
                    select new { Property = prop, Attr = ((InstanceAttribute)attrs.First()) };
        foreach (var pair in props)
        {
            object value = !pair.Attr.IsConstructorCall && pair.Attr.Values.Length > 0
                            ? pair.Attr.Values[0]
                            : Activator.CreateInstance(pair.Property.PropertyType, pair.Attr.Values);
            pair.Property.SetValue(obj, value, null);
        }
    }
}
用法示例:

public class Simple : DefaultValueInitializer
{
    [Instance("StringValue")]
    public string StringValue { get; set; }
    [Instance]
    public List<string> Items { get; set; }
    [Instance(true, 3,4)]
    public Point Point { get; set; }
}

public static void Main(string[] args)
{
    var obj = new Simple
        {
            Items = {"Item1"}
        };
    Console.WriteLine(obj.Items[0]);
    Console.WriteLine(obj.Point);
    Console.WriteLine(obj.StringValue);
}

我认为这会使你的默认值为false

private bool _SomeFlagSet = false;
public bool SomeFlag
{
    get
    {
        if (!_SomeFlagSet)
            SomeFlag = false;        

        return SomeFlag;
    }
    set
    {
        if (!_SomeFlagSet)
            _SomeFlagSet = true;

        SomeFlag = value;        
    }
}
从C 6.0开始,我们可以为自动实现的属性指定默认值

public string Name { get; set; } = "Some Name";
我们还可以创建只读的自动实现属性,如:

public string Name { get; } = "Some Name";

请参阅:

使用构造函数,因为当构造函数完成时,
施工完毕。属性类似于类所持有的状态,如果必须初始化默认状态,则可以在构造函数中进行初始化。

在构造函数中。构造函数的目的是初始化它的数据成员。

在C 6.0中,这是轻而易举的事! 您可以在类声明本身、属性声明语句中执行此操作

public class Coordinate
{ 
    public int X { get; set; } = 34; // get or set auto-property with initializer

    public int Y { get; } = 89;      // read-only auto-property with initializer

    public int Z { get; }            // read-only auto-property with no initializer
                                     // so it has to be initialized from constructor    

    public Coordinate()              // .ctor()
    {
        Z = 42;
    }
}

除了已经接受的答案外,对于希望将默认属性定义为其他属性函数的场景,您可以在C6.0和更高版本上使用表达式体表示法,以获得更优雅和简洁的构造,如:

public class Person{

    public string FullName  => $"{First} {Last}"; // expression body notation

    public string First { get; set; } = "First";
    public string Last { get; set; } = "Last";
}
您可以按以下方式使用上述内容

    var p = new Person();

    p.FullName; // First Last

    p.First = "Jon";
    p.Last = "Snow";

    p.FullName; // Jon Snow
为了能够使用上面的=>符号,属性必须是只读的,并且不能使用get accessor关键字

有关

的详细信息在C 6.0及更高版本中,您可以执行以下操作:

对于只读属性

对于可写和可读属性

在当前版本的C7.0中,您可以这样做:代码段显示了如何使用表达式体的get/set访问器,以便在与支持字段一起使用时更加紧凑

private string label = "Default Value";

// Expression-bodied get / set accessors.
public string Label
{
   get => label;
   set => this.label = value; 
 }
你可以这样简单地说


我知道这是一个老问题,但当我在寻找如何使用覆盖选项继承默认值时,我想到了这个问题

//base class
public class Car
{
    public virtual string FuelUnits
    {
        get { return "gasoline in gallons"; }
        protected set { }
    }
}
//derived
public class Tesla : Car
{
    public override string FuelUnits => "ampere hour";
}
在C 9.0中使用了init关键字-声明只读自动属性的非常有用和复杂的方法:

宣布:

class Person 
{ 
    public string Name { get; init; } = "Anonymous user";
}
~levely~使用:

// 1. Person with default name
var anonymous = new Person();
Console.WriteLine($"Hello, {anonymous.Name}!");
// > Hello, Anonymous user!


// 2. Person with assigned value
var me = new Person { Name = "@codez0mb1e"};
Console.WriteLine($"Hello, {me.Name}!");
// > Hello, @codez0mb1e!


// 3. Attempt to re-assignment Name
me.Name = "My fake"; 
// > Compilation error: Init-only property can only be assigned in an object initializer

返回\u名称??默认名称;也许更清楚的是your@abatishchev:虽然那不一样。Crusibles代码将在字符串为或null时返回默认名称,但使用您的方法将仅在字符串为null时返回默认名称。此外,是否??或IsNullOrEmpty更为明确。该点是默认值,因此可为空的检查将忽略该点。基思的回答通过在Ctor中初始化它来证明这一点。如果是dB,我看不出与使用默认列值并使其成为非空列有多大区别,而不管类字段的数量如何,这将更有效。我不会否决投票,但敦促开发人员考虑这一点,而不是在属性过程中进行空/空检查。为了澄清每次调用类属性时,它都会进行空/空检查,因为dB只会在插入或更新时进行检查,插入或更新通常占dB工作的20%。相反,可能每个字符串属性都有一个额外的调用,这是cpu周期的浪费,也是一个糟糕的设计选择。此外,现在还有空引用类型,因此处理空引用类型更为常见。@:数据绑定和其他基于反射的工具通常需要属性而不是字段。如果不中断调用代码,则无法将字段重构为自动属性。它看起来可能相同,但生成的代码不同。使用自动属性,调用代码在封面后面调用get_propname和set_propname,而如果字段是字段,则直接访问该字段。是的,这非常旧-我已经修改了我的位置:您也无法跨AppDomain边界访问字段-仅访问属性或方法。如果您的位置已更改,也许您应该编辑/删除此答案。欢迎使用堆栈溢出!正如你所知道的,除非你有一些好的新信息,否则通常不赞成提出这样的老问题。但是,在本例中,其他几个人已经发布了关于DefaultValue属性的信息。如果其他人已经发布了你将要说的内容,单击他们答案旁边数字上方的向上箭头,向上投票更合适。@fire:评论需要50声誉。投票还需要声誉,IIRC.-1,因为这不会将属性初始化为默认值。仅对设计师有效,如之前所有回答中所述,这不起作用。DefaultValueAttribute只是一个序列化提示,它不会将ShowGroup设置为true,因为任何布尔值的默认值都是false。这是错误的;使用构造函数不存在双重赋值问题……哇,这是过去的爆炸。我似乎记得这是基于对规范部分摘录的阅读:。考虑到版本和Roslyn的时间和数量,这种情况很可能不会再发生了。尽管可以使用计数器引用,但无论是否在构造函数中使用初始值或赋值,默认赋值都会自动进行。有一点语义上的差异-字段赋值发生在构造函数调用之前-但是空赋值仍然会发生。请参阅10.4.5所有实例字段…首先初始化为其默认值,然后按照上述说明执行实例字段初始值设定项,使用反射初始化默认值既慢又过。在构造函数上初始化,使用非自动属性或在c 6及以上版本上,使用公认答案中所示的简化表示法
三个例子是一个AutoOffice。另外,考虑示例类C{public DATESETP{{GET;} = DATESTIME.No.;公共DATESTIMEQ= > DATESTIME.NOTE;现在,}属性P和Q都只有一个吸气剂,但是P和Q的行为非常不同!这不是自动属性。我还没有C6.0,正在检查自动属性的默认值需要什么版本。C 6.0是否也不再需要{get;set;}或{get;private set;},否则设置值会被编译器阻止?我认为询问者想要一个自动属性,即在使用just get的类或结构中的非抽象属性;带有分号,通常与set组合;指示编译器应自动生成get访问器的主体。此外,当显式设置为null时,此代码具有还原为默认值的副作用。警告:这不会设置初始值,而是创建返回常量字符串的get访问器。如果FuelUnits的值设置为另一个字符串,FuelUnits将忽略该值并继续返回get中定义的文本字符串。
public int ReadOnlyProp => 2;
public string PropTest { get; set; } = "test";
private string label = "Default Value";

// Expression-bodied get / set accessors.
public string Label
{
   get => label;
   set => this.label = value; 
 }
private string name;
public string Name 
{
    get 
    {
        if(name == null)
        {
            name = "Default Name";
        }
        return name;
    }
    set
    {
        name = value;
    }
}
public sealed  class Employee
{
    public int Id { get; set; } = 101;
}
//base class
public class Car
{
    public virtual string FuelUnits
    {
        get { return "gasoline in gallons"; }
        protected set { }
    }
}
//derived
public class Tesla : Car
{
    public override string FuelUnits => "ampere hour";
}
class Person 
{ 
    public string Name { get; init; } = "Anonymous user";
}
// 1. Person with default name
var anonymous = new Person();
Console.WriteLine($"Hello, {anonymous.Name}!");
// > Hello, Anonymous user!


// 2. Person with assigned value
var me = new Person { Name = "@codez0mb1e"};
Console.WriteLine($"Hello, {me.Name}!");
// > Hello, @codez0mb1e!


// 3. Attempt to re-assignment Name
me.Name = "My fake"; 
// > Compilation error: Init-only property can only be assigned in an object initializer