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

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는 또 다른 유용한 기능인 속성에 액세스 할 때 유효성 검사와 같은 다른 논리도 수행 할 수 있다고 지적합니다.


답변

객체 지향 프로그래밍 원칙에 따르면 클래스의 내부 작업은 외부 세계에서 숨겨져 야합니다. 필드를 공개하면 본질적으로 클래스의 내부 구현을 공개합니다. 따라서 우리는 필드를 속성 (또는 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
}


답변

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


답변

기어를 돌릴 수있는 속성을 사용하는 몇 가지 예를 알려 드리겠습니다.

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

답변

속성을 사용하면 속성 값이 변경 될 때 (일명 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의 속성

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, 특성 NameText표시,하지만됩니다 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 접근자는 새 값을 할당하는 데 사용됩니다.