답변:
속성은 필드를 노출합니다. 필드는 (거의 항상) 클래스에 비공개로 유지되고 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는 또 다른 유용한 기능인 속성에 액세스 할 때 유효성 검사와 같은 다른 논리도 수행 할 수 있다고 지적합니다.
string
인 경우 계약은 다음과 같습니다. 최대 2bil 길이의 문자를 할당하십시오. 속성이 인 DateTime
경우 내 계약은 다음과 같습니다. DateTime 제한 내에서 숫자를 지정하면 찾을 수 있습니다. 작성자가 세터에 제한 조건을 추가하면 해당 제한 조건이 전달되지 않습니다. 그러나 대신 작성자가 유형을에서 (으) string
로 변경하면 Surname
새 성 클래스가 제약 조건을 전달하며 속성에 public Surname LastName
setter 유효성 검사가 없습니다. 또한 Surname
재사용이 가능합니다.
Surname
내 예제에서 재사용이 가능하므로 나중에 속성 설정 기에서 해당 유효성 검사를 코드의 다른 위치로 복사 / 붙여 넣는 것에 대해 걱정할 필요가 없습니다. 성에 대한 비즈니스 규칙을 변경 한 경우 성의 유효성 검사가 여러 위치에 있는지 궁금하지도 않습니다. Value Objects
객체 지향 프로그래밍 원칙에 따르면 클래스의 내부 작업은 외부 세계에서 숨겨져 야합니다. 필드를 공개하면 본질적으로 클래스의 내부 구현을 공개합니다. 따라서 우리는 필드를 속성 (또는 Java의 경우 메소드)으로 감싸서 우리에 따라 코드를 손상시키지 않고 구현을 변경할 수 있습니다. 우리가 속성에 논리를 넣을 수 있다는 것을 알면 필요할 때 유효성 검사 논리 등을 수행 할 수 있습니다. C # 3에는 자동 속성이라는 개념이 혼동 될 수 있습니다. 이를 통해 단순히 속성을 정의 할 수 있으며 C # 3 컴파일러는 개인 필드를 생성합니다.
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
}
public int myVar { get; set; }
실제로 의미 하는 것을 파악하기가 여전히 어려울 수 있습니다 (그리고 그 이유라고 생각합니다) 이 질문에 대한 조회수의 50 % 이상이 해당됩니다.
virtual
그 자체가 객체 지향 프로그래밍의 일부입니다.
virtual
그래도 OOP 자체를 호출하지는 않습니다 . 다형성을 가능하게하는 도구로, OOP를 가능하게하는 핵심 도구 중 하나입니다. 그러나 OOP 자체는 아니며 공개 자동 속성에 대해 본질적으로 OOP가 없습니다. 리플렉션 또는 데이터 바인딩 OOP와 같은 것을 계산하지 않습니다. 일반적으로 나는 그것에 대해 너무 비판적이지는 않지만 대답은 구체적으로 OO 원칙을 코드 예제의 원동력으로 언급했으며 이에 동의하지 않습니다.
기어를 돌릴 수있는 속성을 사용하는 몇 가지 예를 알려 드리겠습니다.
속성을 사용하면 속성 값이 변경 될 때 (일명 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);
}
}
그들 중 많은 사람들이 기술 찬반의 양론 설명했기 때문에 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의 속성
Button
Visual Studio에서 작업했을 수 있습니다 . 그것의 속성이 표시됩니다 PropertyGrid
같은 Text
, Name
우리가 끌어 버튼을 드롭 우리가 속성을 클릭하면 자동으로 클래스 찾을 때 등 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)]
거짓 인 경우에는 표시되지 않습니다 .
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;
}
}
필드는 클래스 또는 구조체에 직접 선언 된 변수입니다. 클래스 또는 구조체에는 인스턴스 필드 또는 정적 필드 또는 둘 다가있을 수 있습니다. 일반적으로, 개인용 또는 보호 된 내게 필요한 옵션이있는 변수에 대해서만 필드를 사용해야합니다 . 클래스가 클라이언트 코드에 노출하는 데이터는 메서드, 속성 및 인덱서를 통해 제공되어야합니다 . 내부 필드에 대한 간접 액세스에 이러한 구성을 사용하면 유효하지 않은 입력 값으로부터 보호 할 수 있습니다.
속성은 읽기, 쓰기 또는 전용 필드의 값을 계산하기위한 유연한 메커니즘을 제공하는 부재이다. 속성은 마치 공개 데이터 멤버 인 것처럼 사용할 수 있지만 실제로는 accessors 입니다. 이를 통해 데이터에 쉽게 액세스 할 수 있으며 방법 의 안전과 유연성을 향상 시키는 데 도움이됩니다 . 속성을 통해 클래스는 구현 또는 확인 코드를 숨기면서 값을 가져오고 설정하는 공개 방법을 노출 할 수 있습니다. get 속성 접근자는 속성 값을 반환하는 데 사용되고 set 접근자는 새 값을 할당하는 데 사용됩니다.
속성은 개체의 공용 인터페이스를 손상시키지 않고 개체의 데이터에 액세스하는 방식을 변경할 수있는 주요 이점이 있습니다. 예를 들어, 추가 유효성 검사를 추가하거나 저장된 필드를 계산 된 필드로 변경해야하는 경우 처음에 필드를 속성으로 노출 한 경우 쉽게 수행 할 수 있습니다. 방금 필드를 직접 노출 한 경우 새 기능을 추가하려면 클래스의 공용 인터페이스를 변경해야합니다. 이러한 변경으로 인해 기존 클라이언트가 손상되어 새 버전의 코드를 사용하기 전에 다시 컴파일해야합니다.
수백만 명의 사람들이 사용하는 .NET Framework와 같이 널리 소비되도록 설계된 클래스 라이브러리를 작성하면 문제가 될 수 있습니다. 그러나 작은 코드 기반 (예 : <= 50K 줄) 내부에서 사용되는 클래스를 작성하는 경우 변경에 의해 악영향을받는 사람이 없기 때문에 실제로 큰 문제는 아닙니다. 이 경우에는 실제로 개인 취향에 달려 있습니다.
속성은 비대칭 액세스를 지원합니다. 즉, getter와 setter 또는 둘 중 하나만 가질 수 있습니다. 마찬가지로 속성은 getter / setter에 대한 개별 접근성을 지원합니다. 필드는 항상 대칭입니다. 즉, 항상 값을 가져오고 설정할 수 있습니다. 단, 초기화 후에는 설정할 수없는 읽기 전용 필드는 예외입니다.
속성은 매우 오랫동안 실행될 수 있으며 부작용이 있으며 예외가 발생할 수도 있습니다. 필드는 빠르며 부작용이 없으며 예외가 발생하지 않습니다. 부작용으로 인해 속성은 각 호출에 대해 다른 값을 반환 할 수 있습니다 (DateTime.Now의 경우와 같이 DateTime.Now는 항상 DateTime.Now와 같지 않음). 필드는 항상 같은 값을 반환합니다.
필드는 out / ref 매개 변수에 사용될 수 있지만 속성은 그렇지 않을 수 있습니다. 속성은 추가 로직을 지원합니다. 이는 무엇보다도 지연로드를 구현하는 데 사용될 수 있습니다.
속성은 값을 가져 오거나 설정하는 의미를 캡슐화하여 추상화 수준을 지원합니다.
대부분 / 모든 경우에 속성을 사용하지만 부작용은 피하십시오.
다른 클래스에서 클래스의 객체에 개인 변수 (필드)에 액세스 할 수있게하려면 해당 변수에 대한 속성을 만들어야합니다.
예를 들어 이름이 "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";
}
}
여기서 두 번째 질문 인 "속성 대신 필드를 사용해야합니까?"는 이 다른 답변 에서 간단히 다루어 지며 이것도 마찬가지입니다. 가 아니라 정말 많은 세부 사항.
일반적으로 다른 모든 답변은 훌륭한 디자인에 대해 주목할 만합니다. 필드 노출보다 속성 노출을 선호합니다. 당신은 아마하지 않지만 정기적으로 자신이 "와우, 내가 대신 재산이 필드를 만들었다하면 될 것입니다 얼마나 나쁜 것을 상상"말을 찾아, 그건 너무 많이 , 당신은 와우 "말을 상황을 생각하는 것이 더 희귀 한 재산이 아니라 여기에 밭을 사용해서 감사합니다. "
그러나 필드가 속성보다 장점이 있다는 점이 있으며 "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 메소드 군 호출시) . 참고 : 이것이 처음 인 경우, 휘발성은 기본적으로 volatile
키워드에서 제공하는 것과 동일한 동작을 수행하는 방법 입니다. 따라서, volatile
이름에서 알 수 있듯이 모든 스레드 안전 문제를 마술처럼 해결하지는 않습니다.
나는 당신이 "오, 나는 속성 대신 필드를 노출하기 시작해야한다"고 주장하는 것처럼 보이고 싶지 않다. 요점은 "ref"또는 "out"매개 변수를 사용하는 호출에서, 특히 값을 추가 한 속성 요소가 필요하지 않은 단순한 값 유형일 수있는 호출에서 이러한 멤버를 정기적으로 사용해야하는 경우, 논쟁이 가능하다.
필드와 속성은 서로 비슷해 보이지만 완전히 다른 2 개의 언어 요소입니다.
필드는 클래스 수준에서 데이터를 저장하는 유일한 메커니즘입니다. 필드는 클래스 범위에서 개념적으로 변수입니다. 클래스 (객체) 인스턴스에 일부 데이터를 저장하려면 필드를 사용해야합니다. 다른 선택은 없습니다. 속성은 데이터를 저장할 수 없지만 그렇게 할 수도 있습니다. 다음을 참조하십시오.
반면에 속성은 데이터를 저장하지 않습니다. 그것들은 필드와 비슷한 방식으로 구문 적으로 호출 할 수있는 메소드 쌍 (get 및 set) 일뿐이며 대부분의 경우 혼란의 근원 인 필드에 액세스합니다 (읽기 또는 쓰기 용). 그러나 속성 메서드는 (고정 프로토 타입과 같은 일부 제한이 있지만) 일반 C # 메서드이기 때문에 일반 메서드로 할 수있는 모든 작업을 수행 할 수 있습니다. 그것은 1000 줄의 코드를 가질 수 있고, 예외를 던지고, 다른 메소드를 호출하고, 가상, 추상 또는 재정의 될 수 있음을 의미합니다. 속성을 특별하게 만드는 것은 C # 컴파일러가 특정 속성 (일반적으로 사용되는 기능)을 검색하는 데 사용할 수있는 일부 추가 메타 데이터를 어셈블리에 저장한다는 사실입니다.
속성 메서드 가져 오기 및 설정에는 다음과 같은 프로토 타입이 있습니다.
PROPERTY_TYPE get();
void set(PROPERTY_TYPE value);
따라서 필드와 해당하는 두 가지 방법을 정의하여 속성을 '에뮬레이션'할 수 있습니다.
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).
속성 메서드는 무엇이든 할 수 있지만 대부분의 경우 개체 필드에 액세스하는 방법의 역할을합니다. 다른 클래스가 필드를 액세스 할 수있게하려면 두 가지 방법으로 수행 할 수 있습니다.
다음은 공개 필드를 사용하는 클래스입니다.
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
키워드 를 적용 할 수 있지만이 방법으로 생성자에서만 읽기 전용 필드를 초기화해야합니다. 또한 필드에 유효하지 않은 값을 저장할 수있는 것은 없습니다.
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
속성 만 포함 하더라도 (또는 모양)이 값을 저장할 수 있으며이 클래스의 객체 크기는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;
}
}
}
보시다시피, 필드는 값을 객체에 저장하는 유일한 방법이기 때문에 컴파일러는 여전히 필드를 사용하여 값을 저장합니다.
보시다시피, 속성과 필드의 사용법 구문은 비슷하지만 개념이 매우 다릅니다.자동 속성 또는 이벤트를 사용하더라도 실제 데이터가 저장된 컴파일러에서 숨겨진 필드를 생성합니다.
외부 세계 (클래스 사용자)가 필드 값에 액세스 할 수 있도록해야하는 경우 공개 또는 보호 필드를 사용하지 마십시오. 필드는 항상 비공개로 표시해야합니다. 속성을 사용하면 값 확인, 형식 지정, 변환 등을 수행 할 수 있으며 일반적으로 향후 수정을 위해 코드를 더 안전하고 읽기 쉽고 확장 가능하게 만듭니다.
(이것은 실제로 의견이어야하지만 의견을 게시 할 수 없으므로 게시물로 적절하지 않은 경우 변명하십시오).
필자는 동등한 속성 def가 필드에 액세스했을 때 속성 대신 공용 필드를 사용하는 것이 권장되는 장소에서 한 번 작업했습니다.
get { return _afield; }
set { _afield = value; }
그들의 추론은 공공 장소가 필요할 경우 나중에 재산으로 전환 될 수 있다는 것이었다. 당시에는 조금 이상해 보였습니다. 이 게시물로 판단하면 여기에 많은 사람들이 동의하지 않는 것처럼 보입니다. 무엇을 바꾸려고한다고 말했 을까요?
편집 :이 장소의 모든 코드베이스가 동시에 컴파일되었으므로 클래스의 공용 인터페이스를 변경 (공개 필드를 속성으로 변경)하는 것이 문제가되지 않을 것이라고 생각했을 수도 있습니다.
기술적으로는 속성이 사용자가 만들거나 컴파일러가 자동으로 만든 필드 주위의 래퍼이기 때문에 차이가 있다고 생각하지 않습니다. 속성의 목적은 캡슐화를 시행하고 간단한 메서드와 유사한 기능을 제공하는 것입니다. 필드를 공용으로 선언하는 것은 나쁜 습관이지만 문제가 없습니다.
속성은 필드를 캡슐화하므로 설정하거나 검색 할 값에 대해 추가 처리를 수행 할 수 있습니다. 필드 값에서 사전 처리 또는 사후 처리를 수행하지 않을 경우 일반적으로 특성을 사용하는 것은 과도합니다.
"자동차"라는 수업이있을 때 속성은 색상, 모양입니다.
여기서 필드는 클래스 범위 내에서 정의 된 변수입니다.
Wikipedia에서- 객체 지향 프로그래밍 :
객체 지향 프로그래밍 (OOP)은 "개체"개념을 기반으로하는 프로그래밍 패러다임입니다. "개체"라는 개념 은 필드 속성으로 데이터 를 포함하는 데이터 구조입니다 . 그리고 종종 방법으로 알려진 절차 형태의 코드 . (강조 추가)
속성은 실제로 객체 동작의 일부이지만 객체 소비자에게 객체 데이터 작업의 착시 / 추억을 제공하도록 설계되었습니다.
필자의 필드 디자인은 필드가 부모에 의해서만 수정되어야하므로 클래스입니다. 결과 변수가 개인이 된 다음 외부 클래스 / 메서드를 읽을 수있는 권한을 부여하기 위해 Get 만 사용하여 속성 시스템을 통과합니다. 필드는 속성에 의해 검색되고 읽기 전용입니다! 수정하려면 메소드 (예 : 생성자)를 거쳐야합니다. 보안을 강화하는이 방법 덕분에 "플랜지"때문에 코드를 더 잘 제어 할 수 있습니다. 하나는 항상 모든 것을 공개적으로 공개 할 수 있으므로 모든 가능한 경우, 변수 / 메소드 / 클래스 등의 개념은 ... 코드 개발, 유지 관리에 도움이됩니다. 예를 들어, 사람이 공공 장소에서 코드를 재개하면 무엇이든 할 수 있으므로 "비논리적" 목적과 관련하여 코드가 작성된 이유의 논리. 내 견해입니다.
고전 모델 개인 필드 / 공용 읽기 전용 속성을 사용할 때 10 개인 필드에 대해 10 개의 공용 속성을 작성해야합니다! 코드가 정말 빠를 수 있습니다. 개인 세터를 발견하고 이제 개인 세터와 함께 공용 속성 만 사용합니다. 세터는 백그라운드에서 개인 필드를 작성합니다.
그래서 내 고전 프로그래밍 스타일은 다음과 같습니다.
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;
}
}
생각해보십시오 :이 방에 들어갈 방과 문이 있습니다. 누가 들어오고 있는지 확인하고 방을 확보하려면 속성을 사용해야합니다. 그렇지 않으면 문이 아니고 모든 사람이 쉽게 규제없이 들어옵니다.
class Room {
public string sectionOne;
public string sectionTwo;
}
Room r = new Room();
r.sectionOne = "enter";
사람들이 섹션에 들어가고 있습니다.
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";
이제 당신은 그 사람을 확인하고 그가 그에게 악한 것이 있는지에 대해 알고 있습니다.
필드는 클래스의 변수입니다. 필드는 액세스 수정자를 사용하여 캡슐화 할 수있는 데이터입니다.
속성은 객체와 관련된 상태 및 데이터를 정의한다는 점에서 필드와 유사합니다.
필드와 달리 속성에는 사람이 데이터를 읽고 쓰는 방법을 제어하는 특수 구문이 있으며이를 get 및 set 연산자라고합니다. 집합 논리는 종종 유효성 검사를 수행하는 데 사용될 수 있습니다.
속성은 특수한 종류의 클래스 멤버입니다. 속성에서 미리 정의 된 Set 또는 Get 메서드를 사용합니다. 개인 속성의 값을 읽거나 쓰거나 변경할 수있는 접근자를 사용합니다.
예를 들어, Employee
name, age 및 Employee_Id에 대한 개인 필드가있는 이라는 클래스를 사용하십시오 . 클래스 외부에서는 이러한 필드에 액세스 할 수 없지만 속성을 통해 이러한 개인 필드에 액세스 할 수 있습니다.
왜 우리는 속성을 사용합니까?
클래스 필드를 공개하고 공개하는 것은 위험합니다. 할당 및 반환되는 항목을 제어 할 수 없기 때문입니다.
예를 들어 이것을 명확하게 이해하기 위해 ID, 비밀번호, 이름을 가진 학생 수업을들을 수 있습니다. 이제이 예에서는 공개 필드의 일부 문제
이 문제를 제거하려면 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;
}
}
추가 정보 : 기본적으로 get 및 set 접근자는 속성 자체만큼 액세스 할 수 있습니다. 보다 제한적인 액세스 수정자를 적용하여 접근 자 액세스 가능성을 개별적으로 (get 및 set) 제어 / 제한 할 수 있습니다.
예:
public string Name
{
get
{
return name;
}
protected set
{
name = value;
}
}
여기서 get은 여전히 공개적으로 액세스되지만 (속성이 공개이므로) set은 보호됩니다 (보다 제한된 액세스 지정자).
속성은 필드를 노출하는 데 사용됩니다. 개인 필드의 값을 읽거나 쓰거나 조작 할 수있는 접근 자 (set, get)를 사용합니다.
속성은 저장 위치의 이름을 지정하지 않습니다. 대신, 값을 읽거나 쓰거나 계산하는 접근자가 있습니다.
속성을 사용하여 필드에 설정된 데이터 유형에 대한 유효성 검사를 설정할 수 있습니다.
예를 들어, 나이가 음수가 될 수 없으므로 양수 값을 허용해야하는 개인 정수 필드 나이가 있습니다.
우리는 getter와 setter와 property를 사용하여 두 가지 방법으로 이것을 할 수 있습니다.
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()
}
}
자동 구현 속성 접근 자와 접근자를 논리 화하지 않으면 자동 구현 속성을 사용할 수 있습니다.
유 때 자동 구현 속성 컴파일을 SE는 개인, 익명의 필드 생성 에만 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;
}
}
우리는 개인적으로 속성을 설정할 수 있습니다 여기에서 우리는 개인적으로 자동 속성을 설정할 수 있습니다 (클래스에서 설정)
public int MyProperty
{
get; private set;
}
이 코드로 동일한 결과를 얻을 수 있습니다. 이 속성 집합에서는 값을 필드로 직접 설정해야하므로 기능을 사용할 수 없습니다.
private int myProperty;
public int MyProperty
{
get { return myProperty; }
}
대부분의 경우 변수 이름 ( field ) 과 달리 액세스하는 속성 이름이 될 것입니다. 그 이유는 .NET 및 C #에서 특히 클래스 내의 모든 데이터 조각을 보호하는 것이 좋습니다. 클래스와 연결되어 있기 때문에 인스턴스 변수인지 정적 변수 (클래스 변수)인지 여부입니다.
당신이 정의 할 수 있도록 해당 속성과 그 모든 변수를 보호 세트 얻을 접근을 하고 데이터의 그 조각을 조작 할 때 검증 등의 작업을 수행합니다.
그러나 Math 클래스 (시스템 네임 스페이스) 와 같은 다른 경우에는 클래스 에 내장 된 몇 가지 정적 속성이 있습니다. 그중 하나는 수학 상수 PI입니다
예. Math.PI
PI는 명확하게 정의 된 데이터의 한 부분이므로 PI의 여러 복사본을 가질 필요는 없으며 항상 같은 값이됩니다. 따라서 정적 변수는 때때로 클래스의 객체간에 데이터를 공유하는 데 사용되지만 데이터의 사본이 하나만 필요한 상수 정보에도 일반적으로 사용됩니다.