C#에서 필드를 속성과 다른 점은 무엇이며 언제 속성 대신 필드를 사용해야 합니까?
질문자 :Community Wiki
속성은 필드를 노출합니다. 필드는 (거의 항상) 클래스에 대해 비공개로 유지되어야 하며 get 및 set 속성을 통해 액세스해야 합니다. 속성은 클래스를 사용하는 항목이 액세스하는 외부 방식에 영향을 주지 않으면서 필드를 변경할 수 있도록 하는 추상화 수준을 제공합니다.
public class MyClass { // this is a field. It is private to your class and stores the actual data. private string _myField; // this is a property. When accessed it uses the underlying field, // but only exposes the contract, which will not be affected by the underlying field public string MyProperty { get { return _myField; } set { _myField = value; } } // This is an AutoProperty (C# 3.0 and higher) - which is a shorthand syntax // used to generate a private field for you public int AnotherProperty { get; set; } }
@Kent는 속성이 필드를 캡슐화하는 데 필요하지 않으며 다른 필드에서 계산을 수행하거나 다른 용도로 사용할 수 있다고 지적합니다.
@GSS는 속성에 액세스할 때 유효성 검사와 같은 다른 논리를 수행할 수도 있다고 지적합니다. 또 다른 유용한 기능입니다.
Community Wiki
객체 지향 프로그래밍 원칙에 따르면 클래스의 내부 작업은 외부 세계로부터 숨겨져야 합니다. 필드를 노출하면 본질적으로 클래스의 내부 구현이 노출됩니다. 따라서 우리는 우리에게 의존하는 코드를 깨뜨리지 않고 구현을 변경할 수 있는 능력을 제공하기 위해 속성(또는 자바의 경우 메소드)으로 필드를 래핑합니다. 속성에 논리를 넣을 수 있으므로 필요한 경우 유효성 검사 논리 등을 수행할 수도 있습니다. C# 3에는 autoproperties라는 개념이 혼동될 수 있습니다. 이를 통해 Property를 간단히 정의할 수 있으며 C#3 컴파일러는 우리를 위해 private 필드를 생성할 것입니다.
public class Person { private string _name; public string Name { get { return _name; } set { _name = value; } } public int Age{get;set;} //AutoProperty generates private field for us }
Community Wiki
중요한 차이점은 인터페이스는 속성을 가질 수 있지만 필드는 가질 수 없다는 것입니다. 이것은 나에게 속성이 클래스의 공개 인터페이스를 정의하는 데 사용되어야 하는 반면 필드는 클래스의 비공개 내부 작업에서 사용되어야 한다는 것을 강조합니다. 원칙적으로 나는 공개 필드를 거의 생성하지 않으며 유사하게 비공개 속성도 거의 생성하지 않습니다.
Community Wiki
기어를 돌릴 수 있는 속성을 사용하는 몇 가지 예를 보여 드리겠습니다.
- Lazy Initialization : 로드하는 데 비용이 많이 들지만 코드의 일반적인 실행에서 그다지 많이 액세스되지 않는 개체의 속성이 있는 경우 속성을 통해 로드를 지연할 수 있습니다. 그렇게 하면 그냥 거기에 있지만 다른 모듈이 처음 해당 속성을 호출하려고 할 때 기본 필드가 null인지 확인합니다. 그렇다면 호출 모듈에 알려지지 않은 상태로 계속 진행하여 로드합니다. 이렇게 하면 개체 초기화 속도를 크게 높일 수 있습니다.
- Dirty Tracking: StackOverflow에 대한 내 질문에서 실제로 배웠습니다. 실행 중에 값이 변경되었을 수 있는 개체가 많은 경우 속성을 사용하여 데이터베이스에 다시 저장해야 하는지 여부를 추적할 수 있습니다. 개체의 단일 속성이 변경되지 않은 경우 IsDirty 플래그가 트립되지 않으므로 데이터베이스에 다시 가져와야 할 항목을 결정할 때 저장 기능이 해당 플래그를 건너뜁니다.
Community Wiki
속성을 사용하면 속성 값이 변경될 때(PropertyChangedEvent라고도 함) 또는 취소를 지원하도록 값이 변경되기 전에 이벤트를 발생시킬 수 있습니다.
(직접 접근) 필드에서는 불가능합니다.
public class Person { private string _name; public event EventHandler NameChanging; public event EventHandler NameChanged; public string Name{ get { return _name; } set { OnNameChanging(); _name = value; OnNameChanged(); } } private void OnNameChanging(){ NameChanging?.Invoke(this,EventArgs.Empty); } private void OnNameChanged(){ NameChanged?.Invoke(this,EventArgs.Empty); } }
Community Wiki
Properties
와 Field
의 기술적 장단점에 대해 설명했으므로 실시간 예제로 들어갈 시간입니다.
1. 속성을 사용하여 읽기 전용 액세스 수준을 설정할 수 있습니다.
dataTable.Rows.Count
및 dataTable.Columns[i].Caption
의 경우를 고려하십시오. DataTable
클래스에서 왔으며 둘 다 우리에게 공개됩니다. 액세스 수준의 차이점은 dataTable.Rows.Count
dataTable.Columns[i].Caption
읽고 쓸 수 있다는 것입니다. Field
통해 가능합니까? 아니요!!! Properties
에서만 수행할 수 있습니다.
public class DataTable { public class Rows { private string _count; // This Count will be accessable to us but have used only "get" ie, readonly public int Count { get { return _count; } } } public class Columns { private string _caption; // Used both "get" and "set" ie, readable and writable public string Caption { get { return _caption; } set { _caption = value; } } } }
2. PropertyGrid의 속성
Visual Studio에서 Button
으로 작업했을 수 있습니다. 그 속성은 Text
, Name
등과 같은 PropertyGrid
표시됩니다. 버튼을 끌어다 놓을 때 속성을 클릭하면 Button
Properties
필터링 PropertyGrid
표시합니다(여기서 PropertyGrid
는 표시되지 않습니다. 공개임에도 불구하고 Field
public class Button { private string _text; private string _name; private string _someProperty; public string Text { get { return _text; } set { _text = value; } } public string Name { get { return _name; } set { _name = value; } } [Browsable(false)] public string SomeProperty { get { return _someProperty; } set { _someProperty= value; } }
PropertyGrid
에는 Name
및 Text
SomeProperty
는 표시되지 않습니다. 왜??? 속성은 받아 들일 수 있기 때문에 속성 . [Browsable(false)]
가 false인 경우에는 표시되지 않습니다.
3. 속성 내에서 명령문을 실행할 수 있습니다.
public class Rows { private string _count; public int Count { get { return CalculateNoOfRows(); } } public int CalculateNoOfRows() { // Calculation here and finally set the value to _count return _count; } }
4. 바인딩 소스에서는 속성만 사용할 수 있습니다.
소스 바인딩 은 코드 줄 수를 줄이는 데 도움이 됩니다. Fields
BindingSource
허용되지 않습니다. 이를 위해 Properties
을 사용해야 합니다.
5. 디버깅 모드
값을 유지하기 위해 Field
를 사용한다고 가정합니다. 어느 시점에서 우리는 해당 필드에 대해 값이 null이 되는 위치를 디버그하고 확인해야 합니다. 코드 행 수가 1000개 이상인 경우에는 수행하기 어려울 것입니다. 이러한 상황에서 우리는 Property
Property
내부에서 디버그 모드를 설정할 수 있습니다.
public string Name { // Can set debug mode inside get or set get { return _name; } set { _name = value; } }
Community Wiki
차이점 - 용도(언제, 왜)
필드 는 클래스 또는 구조체에서 직접 선언되는 변수입니다. 클래스 또는 구조체에는 인스턴스 필드나 정적 필드 또는 둘 다 있을 수 있습니다. 일반적으로 private 또는 protected 액세스 가능성이 있는 변수에만 필드를 사용해야 합니다. 클래스가 클라이언트 코드에 노출하는 데이터는 메서드, 속성 및 인덱서를 통해 제공되어야 합니다. 내부 필드에 대한 간접 액세스에 이러한 구성을 사용하여 잘못된 입력 값을 방지할 수 있습니다.
속성 은 개인 필드의 값을 읽고, 쓰고, 계산하는 유연한 메커니즘을 제공하는 멤버입니다. 속성은 공개 데이터 멤버인 것처럼 사용할 수 있지만 실제로는 접근자 라는 특수 메서드입니다. 이렇게 하면 데이터에 쉽게 액세스할 수 있으며 방법의 안전성과 유연성을 높이는 데 도움이 됩니다. 속성을 사용하면 클래스가 구현 또는 확인 코드를 숨기면서 값을 가져오고 설정하는 공개 방법을 노출할 수 있습니다. get 속성 접근자는 속성 값을 반환하는 데 사용되며 set 접근자는 새 값을 할당하는 데 사용됩니다.
Community Wiki
속성에는 공용 인터페이스를 손상시키지 않고 개체의 데이터에 액세스하는 방식을 변경할 수 있다는 주요 이점이 있습니다. 예를 들어 추가 유효성 검사를 추가하거나 저장된 필드를 계산된 필드로 변경해야 하는 경우 처음에 필드를 속성으로 노출했다면 쉽게 추가할 수 있습니다. 필드를 직접 노출한 경우 클래스의 공용 인터페이스를 변경하여 새 기능을 추가해야 합니다. 이러한 변경으로 인해 기존 클라이언트가 손상되어 새 버전의 코드를 사용하기 전에 클라이언트를 다시 컴파일해야 합니다.
광범위한 사용을 위해 설계된 클래스 라이브러리(예: 수백만 명이 사용하는 .NET Framework)를 작성하면 문제가 될 수 있습니다. 그러나 작은 코드 기반(예: <= 50K 줄) 내에서 내부적으로 사용되는 클래스를 작성하는 경우 변경 사항으로 인해 부정적인 영향을 받는 사람이 아무도 없기 때문에 실제로는 큰 문제가 아닙니다. 이 경우 정말 개인 취향에 따라 다릅니다.
Community Wiki
속성은 비대칭 액세스를 지원합니다. 즉, getter와 setter 또는 둘 중 하나만 가질 수 있습니다. 마찬가지로 속성은 getter/setter에 대한 개별 액세스 가능성을 지원합니다. 필드는 항상 대칭입니다. 즉, 항상 값을 가져오고 설정할 수 있습니다. 이에 대한 예외는 초기화 후에 분명히 설정할 수 없는 읽기 전용 필드입니다.
속성은 매우 오랜 시간 동안 실행될 수 있고 부작용이 있을 수 있으며 예외가 발생할 수도 있습니다. 필드는 빠르고 부작용이 없으며 예외가 발생하지 않습니다. 부작용으로 인해 속성은 각 호출에 대해 다른 값을 반환할 수 있습니다(DateTime.Now의 경우, 즉 DateTime.Now가 DateTime.Now와 항상 같지는 않음). 필드는 항상 동일한 값을 반환합니다.
필드는 out / ref 매개변수에 사용될 수 있지만 속성은 그렇지 않을 수 있습니다. 속성은 추가 논리를 지원합니다. 이것은 무엇보다도 지연 로딩을 구현하는 데 사용할 수 있습니다.
속성은 값을 가져오거나 설정하는 의미를 캡슐화하여 추상화 수준을 지원합니다.
대부분의 / 모든 경우에 속성을 사용하지만 부작용을 피하십시오.
Community Wiki
필드와 속성은 서로 비슷해 보이지만 완전히 다른 두 가지 언어 요소입니다.
필드는 클래스 수준에서 데이터를 저장하는 유일한 메커니즘입니다. 필드는 개념적으로 클래스 범위의 변수입니다. 일부 데이터를 클래스(객체)의 인스턴스에 저장하려면 필드를 사용해야 합니다. 다른 선택은 없습니다. 속성은 데이터를 저장할 수 없지만 그렇게 할 수 있는 것처럼 보일 수 있습니다. 아래를 참조하십시오.
반면에 속성은 데이터를 저장하지 않습니다. 필드와 유사한 방식으로 구문적으로 호출할 수 있는 메서드 쌍(get 및 set)일 뿐이며 대부분의 경우 혼동의 원인이 되는 (읽기 또는 쓰기를 위해) 필드에 액세스합니다. 그러나 속성 메서드는 (고정 프로토타입과 같은 몇 가지 제한 사항이 있는) 일반 C# 메서드이기 때문에 일반 메서드가 할 수 있는 모든 작업을 수행할 수 있습니다. 이는 1000줄의 코드를 가질 수 있고 예외를 던질 수 있고 다른 메서드를 호출할 수 있으며 가상, 추상 또는 재정의될 수도 있음을 의미합니다. 속성을 특별하게 만드는 것은 C# 컴파일러가 널리 사용되는 기능인 특정 속성을 검색하는 데 사용할 수 있는 어셈블리에 일부 추가 메타데이터를 저장한다는 사실입니다.
Get 및 set 속성 메서드에는 다음과 같은 프로토타입이 있습니다.
PROPERTY_TYPE get(); void set(PROPERTY_TYPE value);
따라서 필드와 2개의 해당 메서드를 정의하여 속성을 '에뮬레이션'할 수 있음을 의미합니다.
class PropertyEmulation { private string MSomeValue; public string GetSomeValue() { return(MSomeValue); } public void SetSomeValue(string value) { MSomeValue=value; } }
이러한 속성 에뮬레이션은 표준 C++와 같이 속성을 지원하지 않는 프로그래밍 언어에서 일반적입니다. C#에서는 필드에 액세스하는 방법으로 항상 속성을 선호해야 합니다.
필드만 데이터를 저장할 수 있기 때문에 클래스에 더 많은 필드가 포함될수록 해당 클래스의 더 많은 메모리 개체가 사용됩니다. 반면에 클래스에 새 속성을 추가한다고 해서 해당 클래스의 개체가 더 커지는 것은 아닙니다. 여기 예가 있습니다.
class OneHundredFields { public int Field1; public int Field2; ... public int Field100; } OneHundredFields Instance=new OneHundredFields() // Variable 'Instance' consumes 100*sizeof(int) bytes of memory. class OneHundredProperties { public int Property1 { get { return(1000); } set { // Empty. } } public int Property2 { get { return(1000); } set { // Empty. } } ... public int Property100 { get { return(1000); } set { // Empty. } } } OneHundredProperties Instance=new OneHundredProperties() // !!!!! Variable 'Instance' consumes 0 bytes of memory. (In fact a some bytes are consumed becasue every object contais some auxiliarity data, but size doesn't depend on number of properties).
속성 메서드는 무엇이든 할 수 있지만 대부분의 경우 객체의 필드에 액세스하는 방법으로 사용됩니다. 다른 클래스에서 필드에 액세스할 수 있도록 하려면 2가지 방법으로 할 수 있습니다.
- 필드를 공개로 만들기 - 권장하지 않습니다.
- 속성 사용.
다음은 공개 필드를 사용하는 클래스입니다.
class Name { public string FullName; public int YearOfBirth; public int Age; } Name name=new Name(); name.FullName="Tim Anderson"; name.YearOfBirth=1979; name.Age=40;
코드는 완벽하게 유효하지만 디자인 관점에서 보면 몇 가지 단점이 있습니다. 필드는 읽고 쓸 수 있으므로 사용자가 필드에 쓰는 것을 막을 수 없습니다. readonly
키워드를 적용할 수 있지만 이 방법은 생성자에서만 readonly 필드를 초기화해야 합니다. 또한 필드에 잘못된 값을 저장하는 것을 막는 것은 없습니다.
name.FullName=null; name.YearOfBirth=2200; name.Age=-140;
코드가 유효하고 모든 할당이 비논리적이지만 실행됩니다. Age
는 음수 값을 YearOfBirth
는 먼 미래이며 Age에 해당하지 않으며 FullName
은 null입니다. 필드를 사용하면 class Name
사용자가 이러한 실수를 하는 것을 막을 수 없습니다.
다음은 이러한 문제를 해결하는 속성이 있는 코드입니다.
class Name { private string MFullName=""; private int MYearOfBirth; public string FullName { get { return(MFullName); } set { if (value==null) { throw(new InvalidOperationException("Error !")); } MFullName=value; } } public int YearOfBirth { get { return(MYearOfBirth); } set { if (MYearOfBirth<1900 || MYearOfBirth>DateTime.Now.Year) { throw(new InvalidOperationException("Error !")); } MYearOfBirth=value; } } public int Age { get { return(DateTime.Now.Year-MYearOfBirth); } } public string FullNameInUppercase { get { return(MFullName.ToUpper()); } } }
업데이트된 버전의 클래스에는 다음과 같은 이점이 있습니다.
-
FullName
및YearOfBirth
에 잘못된 값이 있는지 확인합니다. -
Age
는 쓸 수 없습니다.YearOfBirth
와 현재 연도에서 계산됩니다. - 새 속성
FullNameInUppercase
FullName
을 대문자로 변환합니다. 이것은 속성 사용의 약간 인위적인 예입니다. 여기서 속성은 일반적으로 사용자에게 더 적합한 형식으로 필드 값을 표시하는 데 사용됩니다(예:DateTime
형식의 특정 숫자에 현재 로케일 사용).
이 외에도 속성은 일반 .NET 메서드이기 때문에 가상 또는 재정의로 정의할 수 있습니다. 일반 메서드와 같은 속성 메서드에도 동일한 규칙이 적용됩니다.
C#은 또한 속성 메서드에 인덱스 매개 변수가 있는 속성인 인덱서를 지원합니다. 여기 예가 있습니다.
class MyList { private string[] MBuffer; public MyList() { MBuffer=new string[100]; } public string this[int Index] { get { return(MBuffer[Index]); } set { MBuffer[Index]=value; } } } MyList List=new MyList(); List[10]="ABC"; Console.WriteLine(List[10]);
C# 3.0부터 자동 속성을 정의할 수 있습니다. 여기 예가 있습니다.
class AutoProps { public int Value1 { get; set; } public int Value2 { get; set; } }
class AutoProps
에는 속성만 포함되어 있지만(또는 비슷하게 생겼지만) 2개의 값을 저장할 수 있으며 이 클래스의 개체 크기는 sizeof(Value1)+sizeof(Value2)
=4+4=8바이트와 같습니다.
그 이유는 간단합니다. 자동 속성을 정의하면 C# 컴파일러는 숨겨진 필드와 이 숨겨진 필드에 액세스하는 속성 메서드가 있는 속성을 포함하는 자동 코드를 생성합니다. 다음은 컴파일러가 생성하는 코드입니다.
다음은 컴파일된 어셈블리 에서 ILSpy에 의해 생성된 코드입니다. 클래스에는 생성된 숨겨진 필드 및 속성이 포함됩니다.
internal class AutoProps { [CompilerGenerated] [DebuggerBrowsable(DebuggerBrowsableState.Never)] private int <Value1>k__BackingField; [CompilerGenerated] [DebuggerBrowsable(DebuggerBrowsableState.Never)] private int <Value2>k__BackingField; public int Value1 { [CompilerGenerated] get { return <Value1>k__BackingField; } [CompilerGenerated] set { <Value1>k__BackingField = value; } } public int Value2 { [CompilerGenerated] get { return <Value2>k__BackingField; } [CompilerGenerated] set { <Value2>k__BackingField = value; } } }
따라서 보시다시피 컴파일러는 여전히 필드를 사용하여 값을 저장합니다. 필드는 값을 개체에 저장하는 유일한 방법이기 때문입니다.
보시다시피 속성과 필드는 사용 구문이 비슷하지만 매우 다른 개념입니다. 자동 속성이나 이벤트를 사용하더라도 - 숨겨진 필드는 실제 데이터가 저장되는 컴파일러에 의해 생성됩니다.
외부 세계(클래스 사용자)가 필드 값에 액세스할 수 있도록 해야 하는 경우 공개 또는 보호 필드를 사용하지 마십시오. 필드는 항상 비공개로 표시되어야 합니다. 속성을 사용하면 값 확인, 형식 지정, 변환 등을 수행할 수 있으며 일반적으로 향후 수정을 위해 코드를 더 안전하고 읽기 쉽고 확장할 수 있습니다.
Community Wiki
백그라운드에서 속성은 메서드로 컴파일됩니다. 따라서 Name
get_Name()
및 set_Name(string value)
으로 컴파일됩니다. 컴파일된 코드를 연구하면 이것을 볼 수 있습니다. 그래서 그것들을 사용할 때 (매우) 작은 성능 오버헤드가 있습니다. 일반적으로 필드를 외부에 노출하는 경우 항상 속성을 사용하고 값의 유효성 검사를 수행해야 하는 경우 내부적으로 자주 사용합니다.
Community Wiki
개인 변수(필드)가 다른 클래스에서 클래스의 개체에 액세스할 수 있도록 하려면 해당 변수에 대한 속성을 만들어야 합니다.
예를 들어 "id" 및 "name"이라는 이름의 변수가 개인용이지만 이 변수가 클래스 외부의 읽기/쓰기 작업에 필요한 상황이 있을 수 있습니다. 이 상황에서 속성은 속성에 대해 정의된 get/set에 따라 해당 변수를 읽고 쓸 수 있도록 도와줍니다. 속성은 읽기 전용/쓰기 전용/읽기 둘 다일 수 있습니다.
여기 데모가 있습니다
class Employee { // Private Fields for Employee private int id; private string name; //Property for id variable/field public int EmployeeId { get { return id; } set { id = value; } } //Property for name variable/field public string EmployeeName { get { return name; } set { name = value; } } } class MyMain { public static void Main(string [] args) { Employee aEmployee = new Employee(); aEmployee.EmployeeId = 101; aEmployee.EmployeeName = "Sundaran S"; } }
Community Wiki
여기서 두 번째 질문인 "속성 대신 필드를 사용해야 하는 경우는 언제입니까?"는 이 다른 답변 과 이 답변에서도 간략하게 설명되지만 실제로는 그다지 자세히 다루지 않습니다.
일반적으로 다른 모든 대답은 좋은 디자인에 대한 것입니다. 필드를 노출하는 것보다 속성을 노출하는 것을 선호합니다. 당신은 아마 정기적으로 자신의 말을 찾을 수는 없지만, 당신이 와우 "말을 상황을 생각 훨씬 더 드문,"와우, 내가 대신 재산이 필드를 만들었다하면 될 것입니다 얼마나 나쁜 것을 상상 " 재산 대신 들판을 사용하게 된 신에게 감사합니다."
그러나 필드가 속성에 비해 한 가지 장점이 있습니다. 바로 "ref" / "out" 매개변수로 사용할 수 있다는 것입니다. 다음 서명이 있는 메서드가 있다고 가정합니다.
public void TransformPoint(ref double x, ref double y);
다음과 같이 생성된 배열을 변환하기 위해 해당 방법을 사용한다고 가정합니다.
System.Windows.Point[] points = new Point[1000000]; Initialize(points);
X 와 Y 는 속성이기 때문에 가장 빠른 방법은 다음과 같습니다.
for (int i = 0; i < points.Length; i++) { double x = points[i].X; double y = points[i].Y; TransformPoint(ref x, ref y); points[i].X = x; points[i].Y = y; }
그리고 그것은 꽤 좋을 것입니다! 달리 증명할 수 있는 측정값이 없는 한 악취를 던질 이유가 없습니다. 그러나 나는 이것이 기술적으로 다음과 같이 빠를 것이라고 보장하지 않는다고 생각합니다.
internal struct MyPoint { internal double X; internal double Y; } // ... MyPoint[] points = new MyPoint[1000000]; Initialize(points); // ... for (int i = 0; i < points.Length; i++) { TransformPoint(ref points[i].X, ref points[i].Y); }
일부 측정을 직접 수행하면 필드가 있는 버전이 속성이 있는 버전(.NET 4.6, Windows 7, x64, 릴리스 모드, 디버거 연결 안 됨)이 있는 버전보다 약 61%의 시간이 걸립니다. TransformPoint
메서드가 더 비싸질수록 차이가 덜 두드러집니다. 이것을 직접 반복하려면 첫 번째 줄을 주석 처리하고 주석 처리하지 않은 상태에서 실행하십시오.
위의 경우 성능상의 이점이 없더라도 Interlocked 또는 Volatile 계열의 메서드를 호출할 때와 같이 ref 및 out 매개 변수를 사용할 수 있는 것이 도움이 될 수 있는 다른 위치가 있습니다. 참고: 이것이 처음인 경우 Volatile은 기본적으로 volatile
키워드에서 제공하는 것과 동일한 동작을 수행하는 방법입니다. 따라서 volatile
처럼 이름에서 알 수 있듯이 모든 스레드 안전 문제를 마술처럼 해결하지는 못합니다.
"오, 속성 대신 필드를 노출해야 합니다."라고 주장하는 것처럼 보이고 싶지는 않습니다. 요점은 "ref" 또는 "out" 매개변수를 사용하는 호출에서 이러한 멤버를 정기적으로 사용해야 하는 경우, 특히 속성의 부가 가치 요소가 전혀 필요하지 않을 가능성이 있는 단순한 값 유형일 수 있는 경우, 주장을 할 수 있다.
Community Wiki
또한 속성을 사용하면 값을 설정할 때 논리를 사용할 수 있습니다.
따라서 값이 x보다 크면 값을 정수 필드로만 설정하고, 그렇지 않으면 예외를 던진다고 말할 수 있습니다.
정말 유용한 기능입니다.
Community Wiki
스레드 프리미티브를 사용하려면 필드를 사용해야 합니다. 속성은 스레드 코드를 손상시킬 수 있습니다. 그 외에 코리님 말씀이 맞습니다.
Community Wiki
(이건 정말 댓글이 되어야 하는데 댓글을 달 수가 없으니 글로써 적절치 못하더라도 양해 부탁드립니다.)
나는 다음과 같이 동등한 속성 def가 필드에 액세스했을 때 속성 대신 공개 필드를 사용하는 것이 권장되는 장소에서 일한 적이 있습니다.
get { return _afield; } set { _afield = value; }
그들의 추론은 필요하다면 나중에 공공 영역을 재산으로 전환할 수 있다는 것이었다. 당시에는 조금 이상하게 느껴졌습니다. 이 게시물로 판단하면 여기에 동의하는 사람도 많지 않을 것 같습니다. 변화를 시도하기 위해 어떤 말을 했을까요?
편집: 이 위치의 모든 코드 기반이 동시에 컴파일되었음을 추가해야 합니다. 그래서 그들은 클래스의 공개 인터페이스를 변경하는 것(공개 필드를 속성으로 변경하여)이 문제가 아니라고 생각했을 것입니다.
Community Wiki
기술적으로 나는 차이가 없다고 생각합니다. 속성은 사용자가 생성하거나 컴파일러에 의해 자동으로 생성되는 필드를 감싸는 래퍼일 뿐입니다. 속성의 목적은 캡슐화를 적용하고 가벼운 메서드와 같은 기능을 제공하는 것입니다. 필드를 공개로 선언하는 것은 나쁜 습관이지만 문제는 없습니다.
Community Wiki
필드는 일반 멤버 변수 또는 클래스의 멤버 인스턴스입니다. 속성은 값을 가져오고 설정 하는 추상화입니다. 속성은 클래스의 필드를 비공개로 노출하는 경우 필드를 변경하고 검색하는 방법을 제공하기 때문에 접근자라고도 합니다. 일반적으로 멤버 변수를 private로 선언한 다음 해당 속성을 선언하거나 정의해야 합니다.
class SomeClass { int numbera; //Field //Property public static int numbera { get; set;} }
Community Wiki
필드에 대한 내 디자인은 필드가 부모에 의해서만 수정되어야 하므로 클래스가 필요하다는 것입니다. 결과 변수가 비공개가 된 다음 외부 클래스/메서드를 읽을 수 있는 권한을 부여할 수 있도록 Get만 있는 속성 시스템을 거칩니다. 그러면 필드가 속성에 의해 검색되고 읽기 전용입니다! 코드를 수정하려면 메서드(예: 생성자)를 거쳐야 하며 이 방법 덕분에 "플랜지"하므로 코드를 더 잘 제어할 수 있습니다. 항상 모든 것을 공개할 수 있으므로 가능한 모든 경우, 변수/메소드/클래스 등의 개념은 ... 제 생각에는 코드의 개발, 유지 관리에 도움이 될 뿐입니다. 예를 들어 사람이 공개 필드가 있는 코드를 다시 시작하면 코드가 작성된 이유에 대한 논리인 목표와 관련하여 "비논리적"인 모든 작업을 수행할 수 있으므로 모든 작업을 수행할 수 있습니다. 제 관점입니다.
클래식 모델 프라이빗 필드/공개 읽기 전용 속성을 사용할 때 10개의 프라이빗 필드에 대해 10개의 퍼블릭 속성을 작성해야 합니다! 코드는 더 빠르게 커질 수 있습니다. private setter를 발견하고 이제 private setter와 함께 공용 속성만 사용합니다. setter는 백그라운드에서 개인 필드를 만듭니다.
내 오래된 고전 프로그래밍 스타일이 다음과 같은 이유는 다음과 같습니다.
public class MyClass { private int _id; public int ID { get { return _id; } } public MyClass(int id) { _id = id; } }
나의 새로운 프로그래밍 스타일:
public class MyClass { public int ID { get; private set; } public MyClass(int id) { ID = id; } }
Community Wiki
기본 및 일반적인 차이점은 다음과 같습니다.
필드
- 항상 get 및 set 액세스 권한을 모두 부여하십시오.
- 부작용을 일으킬 수 없습니다 (예외 발생, 메서드 호출, 가져오기/설정 중인 필드를 제외한 필드 변경 등).
속성
- 항상 get 및 set 액세스 권한을 모두 부여하는 것은 아닙니다.
- 부작용을 일으킬 수 있음
Community Wiki
속성은 필드를 캡슐화하므로 설정하거나 검색할 값에 대해 추가 처리를 수행할 수 있습니다. 필드 값에 대해 사전 또는 사후 처리를 수행하지 않을 경우 일반적으로 속성을 사용하는 것은 과잉입니다.
Community Wiki
IMO, 속성은 이전에 사용했던 "SetXXX()" "GetXXX()" 함수/메소드/인터페이스 쌍이지만 더 간결하고 우아합니다.
Community Wiki
전통적으로 private 필드는 getter 및 setter 메서드를 통해 설정됩니다. 코드를 줄이기 위해 대신 속성을 사용하여 필드를 설정할 수 있습니다.
Community Wiki
"자동차"라는 클래스가있을 때. 속성은 색상, 모양..
여기서 필드는 클래스 범위 내에서 정의된 변수입니다.
Community Wiki
Wikipedia에서 -- 객체 지향 프로그래밍 :
객체 지향 프로그래밍(OOP)은 종종 속성으로 알려진 필드 형태의 데이터 를 포함하는 데이터 구조인 "객체" 개념에 기반한 프로그래밍 패러다임입니다. 그리고 종종 메소드로 알려진 절차 형태의 코드 . (강조 추가됨)
속성은 실제로 개체의 동작의 일부이지만 개체의 소비자에게 개체의 데이터로 작업하는 환상/추상을 제공하도록 설계되었습니다.
Community Wiki
추가 정보: 기본적으로 get 및 set 접근자는 속성 자체만큼 액세스할 수 있습니다. 더 제한적인 접근 수정자를 적용하여 접근자 접근 가능성을 개별적으로(get 및 set에 대해) 제어/제한할 수 있습니다.
예시:
public string Name { get { return name; } protected set { name = value; } }
여기서 get은 여전히 공개적으로 액세스되지만(속성이 public이므로) set은 보호됩니다(더 제한된 액세스 지정자).
Community Wiki
생각해 보십시오. 이 방으로 들어갈 수 있는 방과 문이 있습니다. 누가 어떻게 들어오는지 확인하고 방을 확보하려면 속성을 사용해야 합니다.
class Room { public string sectionOne; public string sectionTwo; } Room r = new Room(); r.sectionOne = "enter";
사람들이 섹션1에 꽤 쉽게 들어가고 있습니다. 확인이 없었습니다.
class Room { private string sectionOne; private string sectionTwo; public string SectionOne { get { return sectionOne; } set { sectionOne = Check(value); } } } Room r = new Room(); r.SectionOne = "enter";
이제 당신은 그 사람을 확인하고 그에게 악의가 있는지 여부를 압니다.
Community Wiki
필드는 클래스의 변수입니다. 필드는 액세스 한정자를 사용하여 캡슐화할 수 있는 데이터입니다.
속성은 개체와 연결된 상태 및 데이터를 정의한다는 점에서 필드와 유사합니다.
필드와 달리 속성에는 사람이 데이터를 읽고 쓰는 방법을 제어하는 특수 구문이 있습니다. 이를 get 및 set 연산자라고 합니다. 설정 논리는 종종 유효성 검사를 수행하는 데 사용할 수 있습니다.
Community Wiki
속성은 특별한 종류의 클래스 멤버입니다. 속성에서는 미리 정의된 Set 또는 Get 메서드를 사용합니다. 접근자를 사용하여 개인 필드의 값을 읽거나 쓰거나 변경할 수 있습니다.
예를 들어, name, age 및 Employee_Id에 대한 개인 필드가 있는 Employee
라는 클래스를 가정해 보겠습니다. 클래스 외부에서 이러한 필드에 액세스할 수 없지만 속성을 통해 이러한 개인 필드에 액세스할 수 있습니다.
속성을 사용하는 이유는 무엇입니까?
클래스 필드를 공개하고 노출하는 것은 할당 및 반환되는 항목을 제어할 수 없기 때문에 위험합니다.
예를 들어 이것을 명확하게 이해하기 위해 ID, 암호, 이름이 있는 학생 클래스를 살펴보겠습니다. 이제 이 예에서 공개 필드에 대한 몇 가지 문제
- ID는 -ve가 아니어야 합니다.
- 이름을 null로 설정할 수 없습니다.
- 합격 표시는 읽기 전용이어야 합니다.
- 학생 이름이 누락된 경우 이름 없음을 반환해야 합니다.
이 문제를 제거하려면 Get 및 set 메서드를 사용합니다.
// A simple example public class student { public int ID; public int passmark; public string name; } public class Program { public static void Main(string[] args) { student s1 = new student(); s1.ID = -101; // here ID can't be -ve s1.Name = null ; // here Name can't be null } }
이제 get 및 set 메소드의 예를 들어보겠습니다.
public class student { private int _ID; private int _passmark; private string_name ; // for id property public void SetID(int ID) { if(ID<=0) { throw new exception("student ID should be greater then 0"); } this._ID = ID; } public int getID() { return_ID; } } public class programme { public static void main() { student s1 = new student (); s1.SetID(101); } // Like this we also can use for Name property public void SetName(string Name) { if(string.IsNullOrEmpty(Name)) { throw new exeception("name can not be null"); } this._Name = Name; } public string GetName() { if( string.IsNullOrEmpty(This.Name)) { return "No Name"; } else { return this._name; } } // Like this we also can use for Passmark property public int Getpassmark() { return this._passmark; } }
Community Wiki
속성은 필드를 노출하는 데 사용됩니다. 그들은 private 필드의 값을 읽거나 쓰거나 조작할 수 있는 접근자(set, get)를 사용합니다.
속성은 저장 위치의 이름을 지정하지 않습니다. 대신 값을 읽거나 쓰거나 계산하는 접근자가 있습니다.
속성을 사용하여 필드에 설정된 데이터 유형에 대한 유효성 검사를 설정할 수 있습니다.
예를 들어 age에 개인 정수 필드가 있는데 age는 음수일 수 없으므로 양수 값을 허용해야 합니다.
getter 및 setter를 사용하고 속성을 사용하는 두 가지 방법으로 이를 수행할 수 있습니다.
Using Getter and Setter // field private int _age; // setter public void set(int age){ if (age <=0) throw new Exception(); this._age = age; } // getter public int get (){ return this._age; } Now using property we can do the same thing. In the value is a key word private int _age; public int Age{ get{ return this._age; } set{ if (value <= 0) throw new Exception() } }
자동 구현 속성 get 및 set 접근자에서 로직을 수행하지 않으면 자동 구현 속성을 사용할 수 있습니다.
자동 구현 속성 컴파일을 사용하면 get 및 set 접근자를 통해서만 액세스할 수 있는 비공개 익명 필드가 생성됩니다.
public int Age{get;set;}
추상 속성 추상 클래스에는 파생 클래스에서 구현되어야 하는 추상 속성이 있을 수 있습니다.
public abstract class Person { public abstract string Name { get; set; } public abstract int Age { get; set; } } // overriden something like this // Declare a Name property of type string: public override string Name { get { return name; } set { name = value; } }
속성을 비공개로 설정할 수 있습니다. 여기서 auto 속성을 비공개로 설정할 수 있습니다(클래스에서 로 설정).
public int MyProperty { get; private set; }
이 코드로 동일한 결과를 얻을 수 있습니다. 이 속성 집합에서는 값을 필드에 직접 설정해야 하므로 사용할 수 없습니다.
private int myProperty; public int MyProperty { get { return myProperty; } }
Community Wiki
출처 : http:www.stackoverflow.com/questions/295104/what-is-the-difference-between-a-field-and-a-property
'etc. > StackOverFlow' 카테고리의 다른 글
\d [0-9]보다 덜 효율적입니다. (0) | 2023.04.20 |
---|---|
생성자와 ngOnInit의 차이점 (0) | 2023.04.20 |
Node.js의 디렉토리에 있는 모든 파일의 이름 목록을 어떻게 얻습니까? (0) | 2023.04.20 |
모든 방법을 통해 UTF-8 (0) | 2023.04.20 |
CSS 클래스 이름/선택기에서 유효한 문자는 무엇입니까? (0) | 2023.04.20 |