c# getter setter




你如何給C#自動屬性一個默認值? (15)

你如何給C#自動屬性一個默認值? 我要么使用構造函數,要么恢復到舊的語法。

使用構造函數:

class Person 
{
    public Person()
    {
        Name = "Default Name";
    }
    public string Name { get; set; }
}

使用正常的屬性語法 (使用默認值)

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

有沒有更好的辦法?


在C#6.0中,這是一件輕而易舉的事!

您可以在Class聲明本身的屬性聲明語句中執行它。

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


一點完整的樣品:

using System.ComponentModel;

private bool bShowGroup ;
[Description("Show the group table"), Category("Sea"),DefaultValue(true)]
public bool ShowGroup
{
    get { return bShowGroup; }
    set { bShowGroup = value; }
}

使用構造函數是因為“當構造函數完成時,施工應該完成”。 屬性就像你的類所持有的狀態,如果你必須初始化一個默認狀態,你可以在你的構造函數中這樣做。


C#(6.0)及更高版本中 ,您可以執行以下操作:

用於Readonly屬性

public int ReadOnlyProp => 2;

對於Writable和Readable屬性

public string PropTest { get; set; } = "test";

在當前版本的C#(7.0)中 ,您可以執行以下操作:(該代碼片段顯示瞭如何使用表達式get / set訪問器在使用後備字段時更加緊湊)

private string label = "Default Value";

// Expression-bodied get / set accessors.
public string Label
{
   get => label;
   set => this.label = value; 
 }

在C#5及更早版本中,為了賦予自動實現的屬性默認值,您必須在構造函數中完成。

自C#6.0以來,包含了自動屬性初始值設定項的功能。 語法是:

public int X { get; set; } = x; // C# 6 or higher

在構造函數中。 構造函數的目的是初始化它的數據成員。


就我個人而言,如果除了汽車財產之外不會做任何事情,我根本看不出把它變成財產的問題。 只要把它作為一個領域。 這些項目的封裝優勢只是紅鯡魚,因為它們背後沒有任何封裝。 如果您需要更改底層實現,您仍然可以自由地將它們重構為屬性,而不會破壞任何相關代碼。

嗯......也許這將成為它後面自己問題的主題


我的解決方案是使用自定義屬性,通過常量或使用屬性類型初始值設定項提供默認值屬性初始化。

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

輸出:

Item1
(X=3,Y=4)
StringValue

我認為這樣做會為你帶來SomeFlag默認值為false。

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

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

        SomeFlag = value;        
    }
}

澄清,是的,你需要在類派生對象的構造函數中設置默認值。 您將需要確保構造函數存在與正確的訪問修飾符在建築使用。 如果對像沒有實例化,例如它沒有構造函數(例如靜態方法),那麼可以通過該字段設置默認值。 這裡的推理是對象本身只會被創建一次,並且你沒有實例化它。

@Darren Kopp - 很好的答案,乾淨,正確。 並且要重申,您可以為抽象方法編寫構造函數。 編寫構造函數時,只需從基類訪問它們即可:

基類的構造函數:

public BaseClassAbstract()
{
    this.PropertyName = "Default Name";
}

Derived / Concrete / Sub-Class的構造函數:

public SubClass() : base() { }

這裡的要點是,從基類中繪製的實例變量可能會隱藏您的基本字段名稱。 使用“this”設置當前實例化的對象值。 將允許您針對當前實例正確地形成對象,並在您要實例化它的位置所需的權限級別(訪問修飾符)。


當你為變量內聯一個初始值時,它將在構造函數中隱式地完成。

我認為這個語法在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; }
}

這樣可以清楚地控制訂單值的分配。

從C#6開始有一個新的方法:

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

除了已經接受的答案之外,對於想要將默認屬性定義為其他屬性的函數時 ,您可以在C#6.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訪問器關鍵字。

有關MSDN詳細信息


類型道具和按下按鈕“選項卡”和Visual Studio建議您遵循代碼,

public int MyProperty { get; set; }

在您可以更改修飾符,數據類型,名稱並輕鬆分配設置並獲取值後。

如果你需要在另一個類中使用一些變量

public static int MyProperty { get; set; }

在代碼中,您可以分配變量

MyProperty=1;

在另一個課程中你可以使用這個,

MessageBox.Show(Classname.MyProperty);

public Class ClassName{
    public int PropName{get;set;}
    public ClassName{
        PropName=0;  //Default Value
    }
}




automatic-properties