Câu hỏi Làm thế nào để bạn cung cấp cho một C # Auto-Property một giá trị mặc định?


Làm thế nào để bạn cung cấp cho một C # Auto-Property một giá trị mặc định? Tôi hoặc là sử dụng các nhà xây dựng, hoặc trở lại cú pháp cũ.

 Sử dụng Constructor:

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

Sử dụng cú pháp thuộc tính bình thường  (với giá trị mặc định)

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

Có cách nào tốt hơn?


1424
2017-09-02 21:29


gốc


Nó gây hiểu lầm, nó thậm chí còn nói trong IntelliSense, "Đặt giá trị mặc định cho một thuộc tính", nhưng trên MSDN nó nói, "DefaultValueAttribute sẽ không làm cho thành viên được tự động khởi tạo với giá trị của thuộc tính. Bạn phải đặt giá trị ban đầu trong mã của bạn. ", Urg! - Chris
Đây là một trong số ít nơi vb.net có mặt trên rõ ràng, họ có thể đặt giá trị mặc định cho các thuộc tính trong định nghĩa. - Blindy
Tại sao bạn không muốn quay lại thuộc tính với trường khởi tạo? Đây là cách trình biên dịch cài đặt các thuộc tính tự động. Ngoài ra một trường rõ ràng có lợi thế mà bạn có thể khai báo nó readonly. - finnw
@finnw IMO đó là về cải thiện khả năng đọc mã. - Keith
Đây là điều duy nhất tôi yêu thích VB.NET trên C #. Public Property MyName As String = "Default Name" - Alex Yeung


Các câu trả lời:


Trong C # 5 và trước đó, để cung cấp cho các thuộc tính tự động thực hiện một giá trị mặc định, bạn phải thực hiện nó trong một hàm tạo.

Khả năng có bộ khởi tạo thuộc tính tự động được bao gồm kể từ C # 6.0. Cú pháp là:

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

1580
2017-09-02 21:46



bạn không chính xác. các lớp trừu tượng có thể có các hàm tạo. - Darren Kopp
các lớp trừu tượng thường có các hàm tạo được bảo vệ. - Ludovic Chabant
các lớp trừu tượng thường có bất kỳ khả năng truy cập nào bạn cung cấp cho họ. nếu bạn không chỉ định một hàm tạo, bạn luôn có một hàm tạo công khai mặc định - Darren Kopp
Các nhà xây dựng cho các lớp trừu tượng sẽ không bao giờ được cấp quyền truy cập công khai vì chúng không bao giờ có thể được khởi tạo. Để làm như vậy sẽ là một vi phạm FxCop (hy vọng bạn đang sử dụng nó) và vi phạm Nguyên tắc Thiết kế Khuôn khổ .NET - amazon.com/Framework-Design-Guidelines-Conventions-Libraries/dp/… - Dave Black
@HankSchultz không, khởi tạo đối tượng chỉ là đường trình biên dịch hiện. những gì thực sự được phát ra là: var person = new Person(); persion.Name = "My Value"; Constructor luôn chạy trước - Darren Kopp


Chỉnh sửa 1/2/15

Với C # 6, bạn có thể khởi tạo các thuộc tính tự động trực tiếp (cuối cùng!), Hiện tại có các câu trả lời khác trong chuỗi mô tả điều đó.

Đối với C # 5 trở xuống:

Mặc dù mục đích sử dụng của thuộc tính là không thực sự thiết lập các giá trị của các thuộc tính, nhưng bạn có thể sử dụng sự phản chiếu để luôn thiết lập chúng ...

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

242
2018-06-22 18:14



Có, Đó là câu trả lời: [System.ComponentModel.DefaultValue (GiveAnyTypeOfDefaultValueHere)] - WAP Guy
1 cho sự khéo léo, nhưng điều này có thể thực sự chậm. Hãy tưởng tượng newing một loạt các mục trong một vòng lặp bên trong mà không nhận ra các nhà xây dựng sử dụng sự phản chiếu ... - Patrick M
Nếu lớp cơ sở sử dụng một hàm dựng tĩnh để tải các thuộc tính và các giá trị vào một từ điển, thì không có phí trên mỗi lớp! - Gayot Fow
U're đề nghị điều thực sự xấu. Nó khá chậm và giới thiệu sự phản chiếu đến lớp khá đơn giản. Nếu nó không phải là quá chậm nó sẽ được okay để sử dụng một số loại il-dệt với thuộc tính như vậy (PostSharp, Fody, vv), nhưng hiệu suất ... - Grigory
Chỉ tốt cho các nhà thiết kế VS và thậm chí không phải trong mọi trường hợp (ví dụ asp.net), anyway .. điều này sẽ không làm bất cứ điều gì tại thời gian chạy. - G.Y


Khi bạn inline một giá trị ban đầu cho một biến nó sẽ được thực hiện ngầm định trong constructor.

Tôi cho rằng cú pháp này là thực tiễn tốt nhất trong C # lên đến 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; }
}

Vì điều này cho phép bạn kiểm soát rõ ràng các giá trị đơn hàng được chỉ định.

Kể từ C # 6 có một cách mới:

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

129
2017-09-04 12:16



Nó chỉ là thực hành tốt nhất nếu các nhà xây dựng cần khởi tạo theo nhiều cách khác nhau (qua nhiều nhà xây dựng). Nếu tất cả chúng khởi tạo cùng một cách, không phải là những gì bạn đang đề xuất thực hành xấu nếu tôi cũng muốn Person (tên chuỗi), và sau đó tôi thêm thuộc tính int ID và tôi có một hàm tạo khác (tên chuỗi, int id)? Vi phạm mở để gia hạn, đóng để sửa đổi. Tôi cho rằng đó là cách tốt nhất để khởi tạo trong dòng miễn là tất cả các nhà thầu khởi tạo thành viên theo cùng một cách. - dbobrowski
@ dbobrowski nếu tôi có nhiều nhà thầu tôi muốn sử dụng public Person(string name, int id) : this() cú pháp, nhưng bạn có một điểm. Điều này cho phép bạn kiểm soát tốt hơn chính xác khi các thuộc tính được khởi tạo với chi phí bảo trì đơn giản của tùy chọn nội tuyến. - Keith
@Keith Tôi thích public Person():this("Default Name"), thay vì đặt Tên hai lần. - ANeves
nếu bạn cần chạy cùng một mã ở một vài nơi, bạn không nên nghĩ đến các thuộc tính phản chiếu và kỳ lạ mà không ai từng nghe đến. bạn trích xuất một phương thức trợ giúp, hoặc ở những nơi phức tạp thực sự, tạo ra một nhà máy (hoặc chỉ thiết kế lại / phá vỡ lớp của bạn alltogether vì nó có lẽ quá phức tạp) - kai


DefaultValueAttribute ONLY làm việc trong vs designer. Nó sẽ không khởi tạo thuộc tính cho giá trị đó.

Xem Thuộc tính DefaultValue không hoạt động với Thuộc tính tự động của tôi


73
2017-09-02 22:44



+1: [DefaultValue] được sử dụng để cho biết giá trị mặc định là gì. Nếu, trong cửa sổ thuộc tính, bạn đặt giá trị cho giá trị mặc định này, thì giá trị sẽ không được ghi vào mã được tạo. Tương tự, các giá trị không mặc định được in đậm trong cửa sổ thuộc tính. Tất nhiên, điều này chỉ hoạt động nếu [DefaultValue] thực sự có giá trị chính xác. Nó không có gì để thực thi điều này. - Roger Lipscombe
DefaultValueAttributekhông chỉ dành cho nhà thiết kế. Tuy nhiên, "giá trị mặc định" không giống như "giá trị ban đầu". - Ben Voigt


Đôi khi tôi sử dụng điều này, nếu tôi không muốn nó thực sự được thiết lập và tồn tại trong db của tôi:

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

        set { _name = value; } 
    }
}

Rõ ràng nếu nó không phải là một chuỗi sau đó tôi có thể làm cho đối tượng nullable (double ?, int?) Và kiểm tra xem nó là null, trả về một mặc định, hoặc trả lại giá trị nó được thiết lập để.

Sau đó, tôi có thể kiểm tra trong kho lưu trữ của mình để xem đó có phải là mặc định của tôi và không tồn tại hay không, hoặc thực hiện kiểm tra cửa sau để xem trạng thái thực của giá trị sao lưu, trước khi lưu.

Hy vọng rằng sẽ giúp!


48
2017-09-02 23:07



return _name ?? "Default Name"; thậm chí có thể rõ ràng hơn là - abatishchev
@abatishchev: mặc dù điều đó không giống nhau. mã độc thân sẽ trả về "Tên mặc định" nếu chuỗi là "" hoặc null, nhưng sử dụng cách tiếp cận của bạn sẽ trả về "Tên mặc định" chỉ trong trường hợp nó là rỗng. Ngoài ra, nó là thảo luận cho dù "??" hoặc "IsNullOrEmpty" rõ ràng hơn. - Sebastian Mach
@phresnel: Nếu giá trị thuộc tính có thể là "" và nó giống như null thì bạn đã đúng. Nếu không, "" là giá trị có ý nghĩa và mã của tôi tốt hơn - abatishchev
private string _name = "Default Name"; public string Name { get { return _name; } set { _name = value; } } - Gilbert
@Gilbert - bạn đã lặp lại một trong các tùy chọn mã được hiển thị trong câu hỏi. Câu trả lời của Crucible đặc biệt cho trường hợp "Tôi không muốn giá trị mặc định vẫn tồn tại trong db của tôi". Đó là, anh ta muốn có thể xác định ở đâu đó cho dù _name đã được viết tới, hay vẫn là null. [Kiểm tra mã của anh ấy hoặc viết mã liên tục _name cho null, bỏ qua viết nó.] - ToolmakerSteve


Bắt đầu với C # 6.0, Chúng tôi có thể gán giá trị mặc định cho các thuộc tính được tự động triển khai.

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

Chúng tôi cũng có thể tạo thuộc tính tự động chỉ đọc như:

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

Xem: C # 6: Phản ứng đầu tiên, Initializers cho các thuộc tính được tự động thực hiện - Jon Skeet


24
2018-04-29 14:40





Trong C # 6.0 đây là một khoe!

Bạn có thể làm điều đó trong Class tự khai báo, trong các tuyên bố khai báo tài sản.

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

17
2017-07-25 19:35



Tôi chưa có C # 6.0 và đang kiểm tra xem phiên bản nào tôi cần cho các giá trị mặc định trên thuộc tính tự động. C # 6.0 cũng loại bỏ sự cần thiết phải có { get; set; } hoặc là { get; private set; } nếu không thì giá trị sẽ bị chặn bởi trình biên dịch? - freefaller


ít mẫu hoàn chỉnh:

using System.ComponentModel;

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

11
2018-06-17 07:44



Điều đó sẽ không hoạt động. DefaultValueAttribute chỉ là một gợi ý tuần tự hóa, nó sẽ không được thiết lập ShowGroup đến true bởi vì giá trị mặc định cho bất kỳ boolean nào là false. - Boris B.


Trong phiên bản của C # (6.0) trở lên, bạn có thể làm :

Đối với thuộc tính chỉ đọc

public int ReadOnlyProp => 2;

Đối với cả thuộc tính có thể ghi và có thể đọc

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

Trong phiên bản hiện tại của C # (7.0), bạn có thể làm: (Đoạn mã thay vì hiển thị cách bạn có thể sử dụng các trình truy xuất get / set được hiển thị thân để làm cho gọn hơn khi sử dụng với các trường sao lưu)

private string label = "Default Value";

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

11
2018-03-15 01:07



Điều này là tốt nhưng chỉ thứ hai trong ba ví dụ là một thuộc tính tự động. - Aluan Haddad