문제

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# 5 이하에서는 자동 구현 속성에 기본값을 제공하려면 생성자에서 수행해야 합니다.

자동 속성 이니셜라이저를 사용하는 기능은 C# 6.0부터 포함되었습니다.구문은 다음과 같습니다.

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

다른 팁

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

변수의 초기값을 인라인하면 어쨌든 생성자에서 암시적으로 수행됩니다.

나는 이 구문이 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"

DefaultValueAttribute는 vs 디자이너에서만 작동합니다.속성을 해당 값으로 초기화하지 않습니다.

보다 DefaultValue 속성이 내 자동 속성에서 작동하지 않습니다.

때때로 나는 이것이 실제로 내 DB에 설정되고 지속되는 것을 원하지 않을 때 이것을 사용합니다.

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

        set { _name = value; } 
    }
}

분명히 문자열이 아닌 경우 개체를 nullable로 만들 수 있습니다( double?, int?) null인지 확인하고 기본값을 반환하거나 설정된 값을 반환합니다.

그런 다음 저장하기 전에 저장소에서 이것이 기본값이고 지속되지 않는지 확인하거나 백도어 체크인을 통해 지원 값의 실제 상태를 확인할 수 있습니다.

도움이 되었기를 바랍니다!

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

C# 6.0부터 시작, 자동 구현 속성에 기본값을 할당할 수 있습니다.

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

다음과 같은 읽기 전용 자동 구현 속성을 만들 수도 있습니다.

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

보다: C# 6:첫 번째 반응, 자동으로 구현된 속성을 위한 초기화 - 작성자: Jon Skeet

버전: C#(6.0) 이상, 넌 할 수있어 :

읽기 전용 속성의 경우

public int ReadOnlyProp => 2;

쓰기 가능 및 읽기 가능 속성 모두에 대해

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#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

약간의 완전한 샘플:

using System.ComponentModel;

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

내 솔루션은 상수 또는 속성 유형 이니셜라이저를 사용하여 기본값 속성 초기화를 제공하는 사용자 지정 특성을 사용하는 것입니다.

[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

C# 6 이상에서는 다음 구문을 간단히 사용할 수 있습니다.

public object Foo { get; set; } = bar;

참고하세요 readonly 속성은 다음과 같이 집합을 생략합니다.

public object Foo { get; } = bar;

할당할 수도 있습니다. readonly 생성자의 자동 속성.

이에 앞서 아래와 같이 답변을 드렸습니다.

생성자에 기본값을 추가하는 것을 피하겠습니다.이를 동적 할당으로 남겨두고 변수가 할당되는 두 지점을 피하십시오(예:기본 유형과 생성자에 있음).일반적으로 이러한 경우에는 일반 속성을 작성하면 됩니다.

또 다른 옵션은 ASP.Net이 수행하는 작업을 수행하고 속성을 통해 기본값을 정의하는 것입니다.

http://msdn.microsoft.com/en-us/library/system.comComponentmodel.defaultvalueattribute.aspx

생성자에서.생성자의 목적은 데이터 멤버를 초기화하는 것입니다.

당신은 DefaultValue속성 또는 ShouldSerialize 및 Reset 메서드 생성자와 함께?디자이너 화면이나 속성 그리드에 표시될 수 있는 클래스를 만드는 경우 이 두 가지 방법 중 하나가 필요하다고 생각합니다.

public Class ClassName{
    public int PropName{get;set;}
    public ClassName{
        PropName=0;  //Default Value
    }
}
private string name;
public string Name 
{
    get 
    {
        if(name == null)
        {
            name = "Default Name";
        }
        return name;
    }
    set
    {
        name = value;
    }
}

개인적으로 저는 자동 속성 이외의 작업을 전혀 수행하지 않는다면 이를 속성으로 만드는 것이 전혀 의미가 없다고 생각합니다.그냥 필드로 남겨두세요.이 항목의 캡슐화 이점은 캡슐화할 항목이 없기 때문에 단지 붉은 청어일 뿐입니다.기본 구현을 변경해야 하는 경우 종속 코드를 손상시키지 않고 자유롭게 이를 속성으로 리팩터링할 수 있습니다.

흠...아마도 이것은 나중에 자체 질문의 주제가 될 것입니다.

명확히 하려면 클래스 파생 객체의 생성자에서 기본값을 설정해야 합니다.사용되는 경우 생성을 위한 적절한 액세스 수정자와 함께 생성자가 존재하는지 확인해야 합니다.객체가 인스턴스화되지 않은 경우생성자가 없습니다(예:정적 메서드) 필드에서 기본값을 설정할 수 있습니다.여기서의 추론은 개체 자체가 한 번만 생성되고 인스턴스화되지 않는다는 것입니다.

@Darren Kopp - 좋은 답변, 깨끗하고 정확합니다.그리고 다시 말하면 추상 메서드에 대한 생성자를 작성할 수 있습니다.생성자를 작성할 때 기본 클래스에서 액세스하면 됩니다.

기본 클래스의 생성자:

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

파생/콘크리트/하위 클래스의 생성자:

public SubClass() : base() { }

여기서 중요한 점은 기본 클래스에서 가져온 인스턴스 변수가 기본 필드 이름을 묻을 수 있다는 것입니다."this"를 사용하여 현재 인스턴스형 객체 값을 설정합니다. 현재 인스턴스 및 필요한 권한 수준 (액세스 수정 자)에 대해 객체를 올바르게 형성 할 수 있습니다.

"생성자가 끝나면 생성도 끝나야 한다"는 이유로 생성자를 사용합니다.속성은 클래스가 보유하는 상태와 유사합니다. 기본 상태를 초기화해야 한다면 생성자에서 초기화하면 됩니다.

이렇게 간단하게 넣을 수 있어요

    public sealed  class Employee
{
    public int Id { get; set; } = 101;
}
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; }
}

나는 이것이 SomeFlag에 false 기본값을 부여하는 데 도움이 될 것이라고 생각합니다.

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

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

        SomeFlag = value;        
    }
}

인라인 초기화, 생성자를 사용하여 초기화하는 것은 나쁜 습관이며 나중에 더 많은 주요 변경 사항이 발생하게 됩니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top