C # 3.0 이상에서 속성과 필드의 차이점

C #에서 필드와 속성의 차이점무엇입니까? 그러나 내 질문은 (내 관점에서) 약간의 차이가 있습니다.

내가 알면

  • 나는 “속성에서만 작동하는 기술”과 함께 수업을 사용하지 않을 것이며
  • getter / setter에서 유효성 검사 코드를 사용하지 않습니다.

속성 설정의 일부 유형의 제어와 같은 차이점 (스타일 / 미래 개발 항목 제외)이 있습니까?

다음과 같은 추가 차이점이 있습니까?

public string MyString { get; set; }

public string myString;

(첫 번째 버전에는 C # 3.0 이상이 필요하며 컴파일러는 개인 필드를 생성한다는 것을 알고 있습니다.)



답변

캡슐화.

두 번째 인스턴스에서는 방금 변수를 정의했으며 첫 번째에는 변수 주위에 getter / setter가 있습니다. 따라서 나중에 변수의 유효성을 검사하기로 결정하면 훨씬 쉬워집니다.

또한 Intellisense에서는 다르게 표시됩니다. 🙂

편집 : OP 업데이트 업데이트 질문-다른 제안을 무시하려면 다른 이유는 단순히 OO 디자인이 좋지 않기 때문입니다. 그리고 그럴만 한 이유가 없다면 항상 공개 변수 / 필드보다 속성을 선택하십시오.


답변

필드와 속성은 동일하게 보이지만 다릅니다. 속성은 메서드이므로 속성에 지원되지 않는 특정 사항 및 속성에는 발생할 수 있지만 필드의 경우에는 전혀 발생하지 않는 사항이 있습니다.

차이점 목록은 다음과 같습니다.

  • 필드는 out/ref인수의 입력으로 사용할 수 있습니다 . 속성은 할 수 없습니다.
  • 필드는 여러 번 호출 될 때 항상 동일한 결과를 생성합니다 (여러 스레드에 대한 문제를 생략 한 경우). 과 같은 속성 DateTime.Now이 항상 자신과 같지는 않습니다.
  • 속성은 예외를 던질 수 있습니다-필드는 절대 그렇게하지 않습니다.
  • 속성에 부작용이 있거나 실행하는 데 시간이 오래 걸릴 수 있습니다. 필드는 부작용이 없으며 주어진 유형에 대해 항상 예상되는 것보다 빠릅니다.
  • 속성은 getter / setters에 대해 서로 다른 접근성을 지원합니다. 필드는 지원하지 않습니다 (그러나 필드를 만들 수는 있음 readonly).
  • 리플렉션을 사용할 때 속성과 필드는 다르게 취급되어 다르게 MemberTypes위치합니다 ( 예 : GetFieldsvs GetProperties)
  • JIT 컴파일러는 필드 액세스와 비교하여 속성 액세스를 매우 다르게 처리 할 수 ​​있습니다. 그러나 동일한 네이티브 코드로 컴파일 할 수는 있지만 차이의 범위가 있습니다.

답변

몇 가지 빠르고 명백한 차이점

  1. 속성에는 접근 자 키워드가있을 수 있습니다.

    public string MyString { get; private set; }
  2. 하위 항목에서 속성을 재정의 할 수 있습니다.

    public virtual string MyString { get; protected set; }

답변

근본적인 차이점은 필드는 지정된 유형의 데이터가 저장되는 메모리의 위치입니다. 특성은 지정된 유형의 값을 검색하거나 설정하기 위해 실행되는 하나 또는 두 개의 코드 단위를 나타냅니다. 이러한 접근 자 메서드의 사용은 필드처럼 동작하는 것처럼 보이는 멤버 (할당 작업의 양쪽에 나타날 수 있음)를 사용하여 구문 적으로 숨겨집니다.


답변

접근자는 필드 이상입니다. 다른 사람들은 이미 몇 가지 중요한 차이점을 지적했으며 하나 더 추가 할 것입니다.

속성은 인터페이스 클래스에 참여합니다. 예를 들면 다음과 같습니다.

interface IPerson
{
    string FirstName { get; set; }
    string LastName { get; set; }
}

이 인터페이스는 여러 가지 방법으로 만족 될 수 있습니다. 예를 들면 다음과 같습니다.

class Person: IPerson
{
    private string _name;
    public string FirstName
    {
        get
        {
            return _name ?? string.Empty;
        }
        set
        {
            if (value == null)
                throw new System.ArgumentNullException("value");
            _name = value;
        }
    }
    ...
}

이 구현에서 우리는 Person클래스가 유효하지 않은 상태가되는 것과 호출자가 할당되지 않은 속성에서 null을 얻는 것을 막고 있습니다.

그러나 디자인을 더욱 발전시킬 수있었습니다. 예를 들어, 인터페이스가 setter를 처리하지 않을 수 있습니다. IPerson인터페이스 소비자 는 속성을 설정하는 것이 아니라 속성을 얻는 데에만 관심이 있다고 말하는 것은 합법적입니다 .

interface IPerson
{
    string FirstName { get; }
    string LastName { get; }
}

Person클래스 의 이전 구현은 이 인터페이스를 충족시킵니다. 호출자가 속성을 설정할 수 있다는 사실은 소비자 (소비자)의 관점에서 의미가 없습니다 IPerson. 구체적인 구현의 추가 기능은 예를 들어 빌더에 의해 고려됩니다.

class PersonBuilder: IPersonBuilder
{
    IPerson BuildPerson(IContext context)
    {

        Person person = new Person();

        person.FirstName = context.GetFirstName();
        person.LastName = context.GetLastName();

        return person;

    }
}

...

void Consumer(IPersonBuilder builder, IContext context)
{
    IPerson person = builder.BuildPerson(context);
    Console.WriteLine("{0} {1}", person.FirstName, person.LastName);
}

이 코드에서 소비자는 부동산 세터에 대해 알지 못합니다. 자신의 사업이 아닙니다. 소비자는 게터 만 필요하며 인터페이스, 즉 계약에서 게터를 얻습니다.

완전히 유효한 또 다른 구현은 IPerson불변 인 개인 클래스와 해당 개인 팩토리입니다.

class Person: IPerson
{
    public Person(string firstName, string lastName)
    {

        if (string.IsNullOrEmpty(firstName) || string.IsNullOrEmpty(lastName))
            throw new System.ArgumentException();

        this.FirstName = firstName;
        this.LastName = lastName;

    }

    public string FirstName { get; private set; }

    public string LastName { get; private set; }

}

...

class PersonFactory: IPersonFactory
{
    public IPerson CreatePerson(string firstName, string lastName)
    {
        return new Person(firstName, lastName);
    }
}
...
void Consumer(IPersonFactory factory)
{
    IPerson person = factory.CreatePerson("John", "Doe");
    Console.WriteLine("{0} {1}", person.FirstName, person.LastName);
}

이 코드에서 샘플 소비자는 다시 한 번 속성을 채울 지식이 없습니다. 소비자는 게터와 구체적인 구현 (이름이 비어있는 경우 테스트와 같은 배후의 비즈니스 논리) 만 처리하며 특수 클래스 (빌더 및 공장)에 맡겨집니다. 이러한 모든 작업은 필드에서 완전히 불가능합니다.


답변

첫번째:

public string MyString {get; set; }

속성입니다; 두 번째 ( public string MyString)는 필드를 나타냅니다.

차이점은 특정 기술 (인스턴스에 대한 ASP.NET 데이터 바인딩)은 속성이 아닌 필드에서만 작동한다는 것입니다. XML 직렬화의 경우에도 마찬가지입니다. 속성 만 직렬화되고 필드는 직렬화되지 않습니다.


답변

대부분의 경우 속성과 필드는 비슷해 보이지만 그렇지 않습니다. 필드에 존재하지 않는 속성에는 제한이 있으며 그 반대도 마찬가지입니다.

다른 사람들이 언급했듯이. 접근자를 비공개로 설정하여 속성을 읽기 전용 또는 쓰기 전용으로 만들 수 있습니다. 필드로는 그렇게 할 수 없습니다. 필드는 불가능하지만 속성은 가상 일 수도 있습니다.

속성을 getXXX () / setXXX () 함수의 구문 설탕으로 생각하십시오. 이것이 그들이 무대 뒤에서 어떻게 구현되는지입니다.