2009-05-09 2 views
16

구조체를 통해 상태 업데이트를 전달하는 WCF 서비스가 있습니다.WPF는 개체의 속성에 바인딩을 지원하지만 필드는 바인딩하지 않는 이유는 무엇입니까?

[DataContract] 
public struct StatusInfo 
{ 
    [DataMember] public int Total; 
    [DataMember] public string Authority; 
} 
... 
public StatusInfo GetStatus() { ... } 

다음과 같이 ViewModel의 속성을 노출합니다.

public class ServiceViewModel : ViewModel 
{ 
    public StatusInfo CurrentStatus 
    { 
     get{ return _currentStatus; } 
     set 
     { 
      _currentStatus = value; 
      OnPropertyChanged(() => CurrentStatus); 
     } 
    }  
} 

XAML은 이렇게 :

<TextBox Text="{Binding CurrentStatus.Total}" /> 

응용 프로그램을 실행할 때 출력 창에 Total 속성을 찾을 수 없다는 오류가 표시됩니다. 나는 체크하고 두 번 체크하고 올바르게 타이핑했다. 오류는 구체적으로 '재산'을 찾을 수 없다는 것을 나타냅니다. 그래서 구조체에 속성을 추가하면 정상적으로 작동합니다. 그러나 이것은 WPF가 필드에 단방향 바인딩을 처리 할 수 ​​없다는 것이 이상한 것 같습니다. 구문 적으로 코드에서 동일한 코드에 액세스하면 StatusInfo 구조체에 대한 사용자 정의보기 모델을 만들어야한다는 것은 어리석은 것처럼 보입니다. WPF 바인딩에 대해 놓친 것이 있습니까? 필드에 바인딩 할 수 있습니까 아니면 속성 만 유일한 방법입니까?

답변

21

바인딩 일반적으로은 필드에서 작동하지 않습니다. 대부분의 바인딩은 부분적으로 ComponentModel PropertyDescriptor 모델에 기반하며, 기본적으로 속성에서 작동합니다. 이렇게하면 알림, 유효성 검사 등을 사용할 수 있습니다 (어떤 것도 필드에서 작동하지 않습니다).

내가 들어갈 수있는 것보다 많은 이유 때문에 공개 입력란은 나쁜 생각입니다. 그들은 속성, 사실이어야합니다. 마찬가지로, 변경 가능한 구조체는 매우 나쁜 아이디어입니다. 적어도 예상치 못한 데이터 손실 (일반적으로 변경 가능한 구조체와 관련됨)으로부터 보호합니다. 이 클래스는 다음과 같아야합니다.

[DataContract] 
public class StatusInfo 
{ 
    [DataMember] public int Total {get;set;} 
    [DataMember] public string Authority {get;set;} 
} 

이제는 생각했던대로 동작합니다. 당신이이 불변 구조체 싶은 경우에, 그 확인 될 것이다 (그러나 데이터 바인딩은 물론, 단 하나의 방법이 될 것이다) 그러나

[DataContract] 
public struct StatusInfo 
{ 
    [DataMember] public int Total {get;private set;} 
    [DataMember] public string Authority {get;private set;} 

    public StatusInfo(int total, string authority) : this() { 
     Total = total; 
     Authority = authority; 
    } 
} 

, 나는이 구조체는 왜 첫 번째 질문 것 처음에는 매우 희귀하다 .NET 언어로 구조체를 작성합니다. WCF "mex"프록시 계층은 어쨌든 (어셈블리 공유를 사용하지 않는 한)이를 소비자의 클래스로 만듭니다. 은 "왜 사용 구조체"응답 ("알 수없는 (구글)")에 대한 답변에서


:

이 내 질문에 대한 응답 인 경우, 그것은 여러 가지 방법으로 잘못된 것입니다. 첫째, 값 유형 은 변수로이 일반적으로 스택에 할당됩니다. 그것들이 힙 (예를 들어 배열 /리스트)에 푸시된다면 클래스와 오버 헤드의 차이는 크지 않습니다. 객체 헤더와 참조의 작은 비트입니다. 구조체는 항상 작은이어야합니다. 여러 필드가있는 경우 크기가 너무 커져서 스택을 죽이거나 블리 팅으로 인해 속도가 느려질 수 있습니다. 또한 구조체는 변경 불가능해야합니다. 이 무엇인지 알지 않는 한.

개체를 나타내는 거의 모든 것이 움직일 수 있어야합니다.

데이터베이스를 공격하는 경우 구조 대 클래스의 속도는 프로세스 외의 작업이나 네트워크를 통한 작업과 비교할 때 문제가되지 않습니다.조금 느린 경우에도 개체를 개체로 취급하는 것과 비교할 때 아무런 의미가 없습니다. 일부 측정 항목

위에 1M 개체 :
struct/field: 50ms 
class/property: 229ms 

다음 (속성 VS 속도 차가 오브젝트에 할당하지 필드)에 기초하여. 따라서 약 5 배 느리지 만 여전히 매우 빠름. 이것이 병목 현상이 아니기 때문에 조기에 최적화하지 마십시오!

using System; 
using System.Collections.Generic; 
using System.Diagnostics; 
struct MyStruct 
{ 
    public int Id; 
    public string Name; 
    public DateTime DateOfBirth; 
    public string Comment; 
} 
class MyClass 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public DateTime DateOfBirth { get; set; } 
    public string Comment { get; set; } 
} 
static class Program 
{ 
    static void Main() 
    { 
     DateTime dob = DateTime.Today; 
     const int SIZE = 1000000; 
     Stopwatch watch = Stopwatch.StartNew(); 
     List<MyStruct> s = new List<MyStruct>(SIZE); 
     for (int i = 0; i < SIZE; i++) 
     { 
      s.Add(new MyStruct { Comment = "abc", DateOfBirth = dob, 
        Id = 123, Name = "def" }); 
     } 
     watch.Stop(); 
     Console.WriteLine("struct/field: " 
        + watch.ElapsedMilliseconds + "ms"); 

     watch = Stopwatch.StartNew(); 
     List<MyClass> c = new List<MyClass>(SIZE); 
     for (int i = 0; i < SIZE; i++) 
     { 
      c.Add(new MyClass { Comment = "abc", DateOfBirth = dob, 
        Id = 123, Name = "def" }); 
     } 
     watch.Stop(); 
     Console.WriteLine("class/property: " 
        + watch.ElapsedMilliseconds + "ms"); 
     Console.ReadLine(); 
    } 
} 
+4

C++ 프로그래머로서 나는 위에 열거 한 의견을 매우 어렵게 느낍니다. 나는 또한 다른 결론에 도달하는 것 같다. 예를 들어 "5 배 느리지 만 매우 빠르고 매우 빠릅니다"라고 말하면됩니다. 반면에 "구조체 사용은 약 5 배 빠르지 만 여전히 매우 느립니다." –

+7

@ 대니얼 한숨, 여기에 우리가 다시 간다. "C++은 모든 것보다 더 빠르며 항상 사용되어야한다"(한숨). 다양한 애플리케이션에서 눈에 띄는 차이는 없습니다. –

+0

나는 C++이 더 빠르다고 말한 적이 없다! 그런 결론은 당신이 진지한 선입견 (또는 오해 일 수도 있음)을 가지고 있음을 나타냅니다. C++은 더 빠르지 만 중요하지는 않습니다. "C++은 더 쉽게 접근 할 수있게 해줍니다. 이것은 중요합니다. 아니면 내 주장을 뒷받침하기 위해 당신이 말한 것을 오해했을 수도 있습니다. –

0

그들은 단지 속성을 지원하는 이유는 단지 추측 할 수는 .NET 프레임 워크에 보편적 인 규칙이 (probably to safeguard binary compatibility)를 변경할 필드를 노출 결코 것 같다 아마 때문에, 그들은 어떻게 든 모든 프로그래머가 동일한을 수행 할 것으로 예상 협약.

또한 필드 및 속성에 동일한 구문으로 액세스하지만 데이터 바인딩은 리플렉션을 사용하므로 속성에 액세스하는 것보다 필드에 액세스 할 때 리플렉션을 다르게 사용해야합니다.

관련 문제