Program Tip

필드와 속성의 차이점은 무엇입니까?

programtip 2020. 9. 27. 13:48
반응형

필드와 속성의 차이점은 무엇입니까?


C #에서 필드를 속성과 다른 점은 무엇이며 속성 대신 필드를 사용해야하는 경우는 언제입니까?


속성은 필드를 노출합니다. 필드는 (거의 항상) 클래스에 대해 비공개로 유지되어야하며 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는 또 다른 유용한 기능인 속성에 액세스 할 때 유효성 검사와 같은 다른 논리를 수행 할 수도 있다고 지적합니다.


객체 지향 프로그래밍 원칙에 따르면 클래스의 내부 작업은 외부 세계에서 숨겨져 야합니다. 필드를 노출하면 본질적으로 클래스의 내부 구현을 노출하는 것입니다. 따라서 우리는 속성 (또는 자바의 경우 메서드)으로 필드를 래핑하여 코드를 깨지 않고 구현을 변경할 수있는 기능을 제공합니다. Property에 로직을 넣을 수있는 것을 보면 우리가 필요한 경우 유효성 검사 로직 등을 수행 할 수도 있습니다. C # 3에는 자동 속성이라는 개념이 혼동 될 수 있습니다. 이를 통해 간단히 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
}

중요한 차이점은 인터페이스는 속성을 가질 수 있지만 필드는 가질 수 없다는 것입니다. 이것은 나에게 속성이 클래스의 공용 인터페이스를 정의하는 데 사용되어야하는 반면 필드는 클래스의 개인 내부 작업에서 사용되어야 함을 강조합니다. 원칙적으로 나는 공개 필드를 거의 생성하지 않으며 유사하게 비공개 속성을 거의 생성하지 않습니다.


기어를 돌릴 수있는 속성을 사용하는 몇 가지 예를 제공합니다.

  • Lazy Initialization : 로드 비용이 많이 들지만 정상적인 코드 실행에서는 그다지 액세스되지 않는 객체의 속성이있는 경우 속성을 통해로드를 지연 할 수 있습니다. 그런 식으로, 그냥 거기에 앉아 있지만 다른 모듈이 해당 속성을 처음 호출하려고 할 때 기본 필드가 null인지 확인합니다. 그렇다면 기본 필드가 null인지 확인하고 호출 모듈에 알려지지 않은 상태로로드합니다. 이것은 객체 초기화 속도를 크게 높일 수 있습니다.
  • Dirty Tracking : 여기 StackOverflow에 대한질문 에서 실제로 배웠습니다 . 실행 중에 값이 변경되었을 수있는 많은 개체가있는 경우 속성을 사용하여 데이터베이스에 다시 저장해야하는지 여부를 추적 할 수 있습니다. 개체의 단일 속성이 변경되지 않은 경우 IsDirty 플래그가 작동하지 않으므로 데이터베이스로 돌아 가야 할 항목을 결정할 때 저장 기능이이를 건너 뜁니다.

속성을 사용하면 속성 값이 변경 될 때 (일명 PropertyChangedEvent) 또는 취소를 지원하도록 값이 변경되기 전에 이벤트를 throw 할 수 있습니다.

(직접 액세스) 필드에서는 불가능합니다.

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(){
   EventHandler localEvent = NameChanging;
   if (localEvent != null) {
     localEvent(this,EventArgs.Empty);
   }
 }

 private void OnNameChanged(){
   EventHandler localEvent = NameChanged;
   if (localEvent != null) {
     localEvent(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의 속성

ButtonVisual 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속성 이 표시되지만 . 왜??? 속성은 받아 들일 수 있기 때문에 속성 . 거짓 인 경우 표시되지 않습니다 .NameTextSomeProperty[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;
        }
   }

차이점-용도 (언제 및 이유)

필드는 클래스 또는 구조체에 직접 선언 된 변수입니다. 클래스 나 구조체는 인스턴스 필드 나 정적 필드 또는 둘 다를 가질 수 있습니다. 일반적으로 비공개 또는 보호 된 액세스 가능성이있는 변수에 대해서만 필드를 사용해야합니다 . 클래스가 클라이언트 코드에 노출하는 데이터는 메서드, 속성 및 인덱서를 통해 제공되어야합니다 . 내부 필드에 대한 간접 액세스를 위해 이러한 구조를 사용하면 잘못된 입력 값으로부터 보호 할 수 있습니다.

속성은 읽기, 쓰기 또는 전용 필드의 값을 계산하기위한 유연한 메커니즘을 제공하는 부재이다. 그들이 공용 데이터 멤버 인 것처럼 속성을 사용할 수 있지만 실제로라는 특별한 방법이 있습니다 접근 . 이를 통해 데이터에 쉽게 액세스 할 수 있으며 방법안전성과 유연성을 높일 수 있습니다 . 속성을 통해 클래스는 구현 또는 확인 코드를 숨기면서 값을 가져오고 설정하는 공개 방법을 노출 할 수 있습니다. get 속성 접근자는 속성 값을 반환하는 데 사용되며 set 접근자는 새 값을 할당하는 데 사용됩니다.


속성은 객체의 공용 인터페이스를 손상시키지 않고 객체의 데이터에 액세스하는 방식을 변경할 수 있다는 주요 이점이 있습니다. 예를 들어 추가 유효성 검사를 추가해야하거나 저장된 필드를 계산 된 필드로 변경해야하는 경우 처음에 필드를 속성으로 노출하면 쉽게 수행 할 수 있습니다. 필드를 직접 노출 한 경우 새 기능을 추가하려면 클래스의 공용 인터페이스를 변경해야합니다. 이러한 변경으로 인해 기존 클라이언트가 손상되어 새 버전의 코드를 사용하기 전에 다시 컴파일해야합니다.

광범위하게 사용하도록 설계된 클래스 라이브러리 (예 : 수백만 명의 사용자가 사용하는 .NET Framework)를 작성하는 경우 문제가 될 수 있습니다. 그러나 작은 코드베이스 (예 : 50K 라인 미만) 내부에서 내부적으로 사용되는 클래스를 작성하는 경우 변경 사항에 부정적인 영향을받지 않는 사람이 없기 때문에 큰 문제가 아닙니다. 이 경우에는 개인 취향에 달려 있습니다.


속성은 비대칭 액세스를 지원합니다. 즉, getter와 setter 중 하나 또는 둘 중 하나만 가질 수 있습니다. 마찬가지로 속성은 getter / setter에 대한 개별 액세스 가능성을 지원합니다. 필드는 항상 대칭입니다. 즉, 항상 값을 가져오고 설정할 수 있습니다. 이에 대한 예외는 초기화 후에 분명히 설정할 수없는 읽기 전용 필드입니다.

속성은 매우 오랜 시간 동안 실행되고 부작용이있을 수 있으며 예외가 발생할 수도 있습니다. 필드는 빠르고 부작용이 없으며 예외가 발생하지 않습니다. 부작용으로 인해 속성은 각 호출에 대해 다른 값을 반환 할 수 있습니다 (DateTime.Now의 경우처럼, 즉 DateTime.Now가 항상 DateTime.Now와 같지는 않음). 필드는 항상 동일한 값을 반환합니다.

필드는 out / ref 매개 변수에 사용할 수 있지만 속성은 사용할 수 없습니다. 속성은 추가 로직을 지원합니다. 이것은 무엇보다도 지연 로딩을 구현하는 데 사용될 수 있습니다.

속성은 값을 가져 오거나 설정하는 것이 무엇이든 캡슐화하여 추상화 수준을 지원합니다.

대부분의 / 모든 경우에 속성을 사용하지만 부작용을 피하십시오.


백그라운드에서 속성은 메서드로 컴파일됩니다. 따라서 Name속성은 get_Name()로 컴파일됩니다 set_Name(string value). 컴파일 된 코드를 살펴보면 알 수 있습니다. 따라서 사용할 때 (매우) 작은 성능 오버 헤드가 있습니다. 일반적으로 필드를 외부에 노출하면 항상 속성을 사용하고 값의 유효성을 검사해야하는 경우 내부적으로 자주 사용합니다.


개인 변수 (필드)가 다른 클래스의 클래스 개체에 액세스 할 수 있도록하려면 해당 변수에 대한 속성을 만들어야합니다.

예를 들어 "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);

XY 는 속성 이기 때문에 가장 빠른 방법은 다음과 같습니다 .

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"매개 변수를 사용하는 호출에서 이러한 멤버를 정기적으로 사용해야하는 경우, 특히 속성의 부가 가치 요소가 필요하지 않은 단순한 값 유형일 수있는 항목에 대해 논쟁을 할 수 있습니다.


또한 속성을 사용하면 값을 설정할 때 논리를 사용할 수 있습니다.

따라서 값이 x보다 크면 정수 필드에 값을 설정하고 싶지만, 그렇지 않으면 예외를 던진다 고 말할 수 있습니다.

정말 유용한 기능입니다.


스레드 프리미티브를 사용하려면 필드를 사용해야합니다. 속성은 스레드 코드를 손상시킬 수 있습니다. 그 외에도 코리가 말한 것은 옳습니다.


(정말 댓글이어야하는데 댓글을 올릴 수 없으니 글로 적합하지 않다면 용서 해주세요)

필자는 다음과 같이 동등한 속성 def가 필드에 액세스했을 때 속성 대신 공용 필드를 사용하는 것이 권장되는 장소에서 일한 적이 있습니다.

get { return _afield; }
set { _afield = value; }

그들의 추론은 필요에 따라 나중에 공용 필드가 속성으로 변환 될 수 있다는 것입니다. 당시 나에게는 조금 이상해 보였습니다. 이 게시물로 판단하면 여기에서도 동의하는 사람은 많지 않은 것 같습니다. 변화를 시도하기 위해 무엇을 말했 을까요?

편집 :이 장소의 모든 코드베이스가 동시에 컴파일되었으므로 클래스의 공용 인터페이스를 변경하는 것 (공용 필드를 속성으로 변경)이 문제가 아니라고 생각했을 수 있습니다.


기술적으로는 속성이 사용자가 생성하거나 컴파일러에 의해 자동으로 생성 된 필드를 감싸는 래퍼이기 때문에 차이가 있다고 생각하지 않습니다. 속성의 목적은 캡슐화를 적용하고 간단한 메서드와 같은 기능을 제공하는 것입니다. 필드를 공용으로 선언하는 것은 나쁜 습관이지만 문제가 없습니다.


필드는 일반 멤버 변수 또는 클래스의 멤버 인스턴스입니다. 속성은 값을 가져오고 설정하기 위한 추상화 입니다. 속성은 클래스의 필드를 비공개로 노출하는 경우 필드를 변경하고 검색하는 방법을 제공하기 때문에 접근 자라고도합니다. 일반적으로 멤버 변수를 private으로 선언 한 다음 속성을 선언하거나 정의해야합니다.

  class SomeClass
  {
     int numbera; //Field

     //Property 
    public static int numbera { get; set;}

  }

속성은 필드를 캡슐화하므로 설정하거나 검색 할 값에 대해 추가 처리를 수행 할 수 있습니다. 필드 값에 대해 사전 또는 사후 처리를 수행하지 않을 경우 속성을 사용하는 것은 일반적으로 과잉입니다.


IMO, 속성은 이전에 사용한 "SetXXX ()" "GetXXX ()"함수 / 메소드 / 인터페이스 쌍일 뿐이지 만 더 간결하고 우아합니다.


전통적으로 private 필드는 getter 및 setter 메서드를 통해 설정됩니다. 코드를 줄이려면 대신 속성을 사용하여 필드를 설정할 수 있습니다.


"자동차"클래스가있을 때. 속성은 색상, 모양 ..

as 필드는 클래스 범위 내에서 정의 된 변수입니다.


Wikipedia에서- 객체 지향 프로그래밍 :

객체 지향 프로그래밍 (OOP)은 "객체"개념을 기반으로하는 프로그래밍 패러다임으로 , 종종 속성으로 알려진 필드의 형태로 데이터 를 포함하는 데이터 구조입니다 . 그리고 종종 방법으로 알려진 절차 형태의 코드 . (강조 추가됨)

속성은 실제로 개체 동작의 일부이지만 개체 소비자에게 개체 데이터 작업의 환상 / 추상을 제공하도록 설계되었습니다.


필자의 필드 디자인은 필드가 부모, 따라서 클래스에 의해서만 수정되어야한다는 것입니다. 결과 변수가 비공개가 된 다음 외부에서 클래스 / 메서드를 읽을 수있는 권한을 부여 할 수 있도록 Get만으로 속성 시스템을 통과합니다. 이 필드는 속성에 의해 검색되고 읽기 전용입니다! 이를 수정하려면 메서드 (예 : 생성자)를 거쳐야합니다. 보안을 강화하는이 방법 덕분에 코드를 "플랜지"하기 때문에 코드를 더 잘 제어 할 수 있습니다. 가능한 모든 경우, 변수 / 메서드 / 클래스 등의 개념은 항상 모든 것을 공개적으로 공개 할 수 있으므로 제 생각에는 코드의 개발, 유지 관리에 도움이 될뿐입니다. 예를 들어, 어떤 사람이 공개 필드가있는 코드를 재개하면 그는 무엇이든 할 수 있으므로 "비논리적"인 일을 할 수 있습니다. 목적과 관련하여 코드가 작성된 이유에 대한 논리. 제 관점입니다.

클래식 모델 프라이빗 필드 / 퍼블릭 읽기 전용 속성을 사용할 때 10 개의 프라이빗 필드에 대해 10 개의 퍼블릭 속성을 작성해야합니다! 코드는 정말 빠르게 커질 수 있습니다. 개인 setter를 발견하고 이제는 개인 setter와 함께 공용 속성 만 사용합니다. setter는 백그라운드에서 private 필드를 만듭니다.

그래서 나의 오래된 고전적인 프로그래밍 스타일은 :

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

필드는 클래스의 변수입니다. 필드는 액세스 수정자를 사용하여 캡슐화 할 수있는 데이터입니다.

속성은 개체와 관련된 상태 및 데이터를 정의한다는 점에서 필드와 유사합니다.

필드와 달리 속성에는 사람이 데이터를 읽고 쓰는 방법을 제어하는 ​​특수 구문이 있으며이를 get 및 set 연산자라고합니다. 세트 로직은 종종 유효성 검사를 수행하는 데 사용될 수 있습니다.


속성은 특별한 종류의 클래스 멤버이며, 속성에서는 미리 정의 된 Set 또는 Get 메서드를 사용합니다. 속성은 개인 필드의 값을 읽거나 쓰거나 변경할 수있는 접근자를 사용합니다.

예를 들어 Employee이름, 나이 및 Employee_Id에 대한 개인 필드가있는 라는 클래스를 사용하겠습니다 . 클래스 외부에서는 이러한 필드에 액세스 할 수 없지만 속성을 통해 이러한 비공개 필드에 액세스 할 수 있습니다.

속성을 사용하는 이유는 무엇입니까?

클래스 필드를 공개하고 노출하는 것은 할당 및 반환되는 항목을 제어 할 수 없기 때문에 위험합니다.

예를 들어 이것을 명확하게 이해하기 위해 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;
    }
}

속성은 필드를 노출하는 데 사용됩니다. 그들은 private 필드의 값을 읽고 쓰거나 조작 할 수있는 접근 자 (set, get)를 사용합니다.

속성은 저장 위치의 이름을 지정하지 않습니다. 대신 값을 읽거나 쓰거나 계산하는 접근자가 있습니다.

속성을 사용하여 필드에 설정된 데이터 유형에 대한 유효성 검사를 설정할 수 있습니다.

예를 들어, 나이는 음수가 될 수 없기 때문에 양수 값을 허용해야한다는 개인 정수 필드 나이가 있습니다.

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()
       }
    }

Auto Implemented 속성 get 및 set 접근 자에서 논리가 없으면 자동 구현 속성을 사용할 수 있습니다.

유 때 자동 구현 속성 컴파일을 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;
     }
  }

속성을 개인적으로 설정할 수 있습니다. 여기서는 auto 속성을 개인적으로 설정할 수 있습니다 (클래스에서 설정).

public int MyProperty
{
    get; private set;
}

이 코드로 동일한 결과를 얻을 수 있습니다. 이 속성 집합에서는 값을 필드에 직접 설정해야하므로 기능을 사용할 수 없습니다.

private int myProperty;
public int MyProperty
{
    get { return myProperty; }
}

생각해보십시오.이 방에 들어갈 방과 문이 있습니다. 누가 들어오고 있는지 확인하고 방을 확보하려면 속성을 사용해야합니다. 그렇지 않으면 문이없고 모든 사람이 규제없이 쉽게 들어올 수 있습니다.

class Room {
   public string sectionOne;
   public string sectionTwo;
}

Room r = new Room();
r.sectionOne = "enter";

사람들은 sectionOne에 아주 쉽게 들어가고 있습니다.

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

이제 당신은 그 사람을 확인하고 그가 그에게 악한 것이 있는지 알고


대부분의 경우 변수 이름 ( field ) 과 반대로 액세스하는 속성 이름이 될 것입니다. 그 이유는 .NET 및 C #에서 특히 클래스 내의 모든 데이터를 보호하는 것이 좋은 방법으로 간주되기 때문입니다. , 인스턴스 변수이든 정적 변수 (클래스 변수)이든 클래스와 연결되어 있기 때문입니다.

당신이 정의 할 수 속성에 대응하여 그 모든 변수를 보호 세트 얻을 접근을 하고 데이터의 그 조각을 조작 할 때 검증 등의 작업을 수행합니다.

그러나 Math 클래스 (시스템 네임 스페이스) 와 같은 다른 경우에는 클래스 에 내장 된 몇 가지 정적 속성이 있습니다. 그중 하나는 수학 상수 PI입니다.

예. Math.PI

PI는 잘 정의 된 데이터 조각이기 때문에 PI의 여러 복사본을 가질 필요가 없으며 항상 동일한 값이됩니다. 따라서 정적 변수는 때때로 클래스의 객체간에 데이터를 공유하는 데 사용되지만 일반적으로 데이터의 복사본 하나만 필요한 상수 정보에도 사용됩니다.


기본 및 일반적인 차이점은 다음과 같습니다.

필드

  • 항상 get 및 set 액세스 권한을 모두 부여하십시오.
  • 부작용을 유발할 수 없습니다 (예외 발생, 메서드 호출, 가져 오기 / 설정중인 필드를 제외한 필드 변경 등)

속성

  • 항상 get 및 set 액세스 권한을 모두 부여 하지는 않습니다.
  • 부작용을 일으킬 있음

필드와 속성은 서로 비슷해 보이지만 완전히 다른 두 가지 언어 요소입니다.

  1. 필드는 클래스 수준에서 데이터를 저장하는 유일한 메커니즘입니다. 필드는 개념적으로 클래스 범위의 변수입니다. 일부 데이터를 클래스 (객체)의 인스턴스에 저장하려면 필드를 사용해야합니다. 다른 선택의 여지가 없습니다. 속성은 데이터를 저장할 수 없지만 그렇게 할 수있는 것처럼 보일 수 있습니다. 아래를 참조하십시오.

  2. 반면 속성은 데이터를 저장하지 않습니다. 이들은 필드와 유사한 방식으로 구문 적으로 호출 될 수있는 메소드 쌍 (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).

속성 메서드는 무엇이든 할 수 있지만 대부분의 경우 개체의 필드에 액세스하는 방법으로 사용됩니다. 다른 클래스에서 필드에 액세스 할 수 있도록하려면 두 가지 방법으로 수행 할 수 있습니다.

  1. 필드를 공개로 설정-권장하지 않습니다.
  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키워드 를 적용 할 수 있지만 이렇게하면 생성자에서만 읽기 전용 필드를 초기화해야합니다. 또한 필드에 유효하지 않은 값을 저장하는 것을 방해하는 것은 없습니다.

name.FullName=null;
name.YearOfBirth=2200;
name.Age=-140;

코드는 유효하며 모든 할당은 비논리적이지만 실행됩니다. Age음수 값 YearOfBirth이 있고 먼 미래이며 Age에 해당하지 않으며 FullNamenull입니다. 필드를 사용하면 사용자가 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());
        }
    }
}

클래스의 업데이트 된 버전은 다음과 같은 장점이 있습니다.

  1. FullNameYearOfBirth유효하지 않은 값을 검사합니다.
  2. Age쓸 수 없습니다. YearOfBirth현재 연도 에서 callculated입니다 .
  3. 새 속성 이 대문자 FullNameInUppercase로 변환 FullName됩니다. 이것은 속성 사용의 약간 인위적인 예입니다. 여기서 속성은 일반적으로 사용자에게 더 적합한 형식으로 필드 값을 표시하는 데 사용됩니다 (예 : 특정 숫자 DateTime형식의 현재 로케일 사용) .

이 외에도 속성은 일반 .NET 메서드이기 때문에 가상 또는 재정의로 정의 할 수 있습니다. 이러한 속성 메서드에는 일반 메서드와 동일한 규칙이 적용됩니다.

C #은 속성 메서드에 index 매개 변수가있는 속성 인 인덱서도 지원합니다. 다음은 그 예입니다.

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

보시다시피 컴파일러는 여전히 필드를 사용하여 값을 저장합니다. 필드는 객체에 값을 저장하는 유일한 방법이기 때문입니다.

보시다시피 속성과 필드의 사용 구문은 비슷하지만 개념은 매우 다릅니다. 자동 속성 또는 이벤트를 사용하더라도 실제 데이터가 저장된 컴파일러에서 숨겨진 필드를 생성합니다.

외부 세계 (클래스 사용자)가 필드 값에 액세스 할 수 있도록해야하는 경우 공용 또는 보호 된 필드를 사용하지 마십시오. 필드는 항상 비공개로 표시되어야합니다. 속성을 사용하면 값 확인, 서식 지정, 변환 등을 수행 할 수 있으며 일반적으로 코드를 더 안전하고 읽기 쉽고 향후 수정을 위해 확장 할 수 있습니다.

참고 URL : https://stackoverflow.com/questions/295104/what-is-the-difference-between-a-field-and-a-property

반응형