etc./StackOverFlow

C# 자동 속성에 초기 값을 제공하는 가장 좋은 방법은 무엇입니까?

청렴결백한 만능 재주꾼 2021. 12. 2. 00:26
반응형

질문자 :bentford


C# 자동 속성에 초기 값을 어떻게 지정합니까?

생성자를 사용하거나 이전 구문으로 되돌립니다.

생성자 사용:

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

일반 속성 구문 사용 (초기 값 포함)

 private string name = "Initial 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

DefaultValueAttribute 는 VS 디자이너(또는 다른 소비자)가 초기 값이 아닌 기본값을 지정하는 데 사용하기 위한 것입니다. (설계된 오브젝트라도 초기값이 기본값입니다.)

컴파일 시 DefaultValueAttribute 는 생성된 IL에 영향을 미치지 않으며 속성을 해당 값으로 초기화하기 위해 읽지 않습니다( DefaultValue 속성이 내 Auto 속성에서 작동하지 않음 참조).

IL에 영향을 미치는 속성의 예는 ThreadStaticAttribute , CallerMemberNameAttribute , ...


Darren Kopp

1/2/15에 수정됨

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

Chuck Rostance

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

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

Keith

때때로 나는 이것을 실제로 설정하고 내 db에 유지하고 싶지 않다면 이것을 사용합니다.

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

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

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

도움이 되기를 바랍니다!


crucible

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

Shiva

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

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

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

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

참조: C# 6: 첫 번째 반응, 자동으로 구현된 속성에 대한 초기화 - Jon Skeet 작성


Habib

C#(6.0) 이상 버전에서는 다음을 수행할 수 있습니다.

읽기 전용 속성의 경우

 public int ReadOnlyProp => 2;

Writable 및 Readable 속성 모두에 대해

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

현재 버전의 C#(7.0) 에서는 다음을 수행할 수 있습니다.

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

ANewGuyInTown

이미 수락된 답변 외에도 기본 속성을 다른 속성 의 함수 로 정의하려는 시나리오의 경우 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 에 대한 세부 정보


brakeroo

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.componentmodel.defaultvalueattribute.aspx


Lex

C# 9.0 에서는 init 키워드 지원이 추가되었습니다. 읽기 전용 자동 속성 선언을 위한 매우 유용하고 정교한 방법입니다.

선언하다:

 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

codez0mb1e

약간의 완전한 샘플:

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

ghiboz

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

 [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

introspected

이렇게 간단하게 넣을 수 있습니다

 public sealed class Employee { public int Id { get; set; } = 101; }

Sunil Dhappadhule

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


RayLoveless

private string name; public string Name { get { if(name == null) { name = "Default Name"; } return name; } set { name = value; } }

ComeIn

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


OwenP

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

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

기본 클래스의 생성자:

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

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

 public SubClass() : base() { }

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


Zack Jannsen

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

FloodMoo

"생성자가 완료되면 생성이 완료되어야 한다"는 이유로 생성자를 사용합니다. 속성은 클래스가 보유하는 상태와 같습니다. 기본 상태를 초기화해야 하는 경우 생성자에서 초기화해야 합니다.


Preet Singh

이것은 이제 오래되었고 내 위치가 변경되었습니다. 나는 후손을 위해 원래의 답변을 남겨두고 있습니다.


개인적으로 auto-property 외에는 아무 것도 하지 않으려면 속성으로 만드는 것이 의미가 없다고 생각합니다. 그냥 필드로 두십시오. 이 항목에 대한 캡슐화 이점은 캡슐화할 뒤에 아무것도 없기 때문에 청어일 뿐입니다. 기본 구현을 변경해야 하는 경우 종속 코드를 손상시키지 않고 이를 속성으로 리팩터링할 수 있습니다.

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


Joel Coehoorn

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

Nag

나는 이것이 오래된 질문이라는 것을 알고 있지만 재정의하는 옵션과 함께 상속되는 기본값을 갖는 방법을 찾을 때 나타났습니다.

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

Jesse Adam

SomeFlag에 기본값이 false인 경우 이것이 가능하다고 생각합니다.

 private bool _SomeFlagSet = false; public bool SomeFlag { get { if (!_SomeFlagSet) SomeFlag = false; return SomeFlag; } set { if (!_SomeFlagSet) _SomeFlagSet = true; SomeFlag = value; } }

user3076134

출처 : http:www.stackoverflow.com/questions/40730/what-is-the-best-way-to-give-a-c-sharp-auto-property-an-initial-value

반응형