2012-12-21 9 views
7

Próbuję utworzyć klasę, która ma wartość, podniesie zdarzenie za każdym razem, gdy wartość zmieni się, i będzie niejawnie konwertować do i od typu, który posiada.Tworzenie klasy obserwowalnej <T>: przeciążanie = operator?

Moim celem jest to, że powinienem być w stanie stworzyć obserwowalną własność klasy i mieć inną klasę (w tym kontrolki WPF), która będzie w stanie odczytać i zapisać do niej tak, jakby był zwykłym ciągiem znaków. Inne klasy mogłyby zachować odniesienie do niego jako obserwowalne, lub nawet ujawnić je jako swoją własność bez konieczności tworzenia nowych zdarzeń.

Oto co mam do tej pory:

using System; 
using System.ComponentModel; 

namespace SATS.Utilities 
{ 
    public class Observable<T> 
    { 
     private T mValue; 

     public event EventHandler ValueChanged; 
     public event PropertyChangedEventHandler PropertyChanged; 

     private void NotifyValueChanged() 
     { 
      if (ValueChanged != null) 
      { 
       ValueChanged(this, new EventArgs()); 
      } 
      if (PropertyChanged != null) 
      { 
       PropertyChanged(this, new PropertyChangedEventArgs("Value")); 
      } 
     } 

     public T Value 
     { 
      get 
      { 
       return mValue; 
      } 
      set 
      { 
       SetValueSilently(value); 
       NotifyValueChanged(); 
      } 
     } 

     public void SetValueSilently(T value) 
     { 
      mValue = value; 
     } 

     public static implicit operator T(Observable<T> observable) 
     { 
      return observable.Value; 
     } 

     public static T operator =(Observable<T> observable, T value) // Doesn't compile! 
     { 
      observable.Value = value; 
      return value; 
     } 
    } 
} 

Problem polega na tym, że operator „=” narzeka, że ​​nie może być przeciążony. Myślę, że ma to sens, ponieważ może prowadzić do różnego rodzaju dziwnych zachowań. Czy istnieje inny sposób osiągnięcia tego, co zamierzam osiągnąć?

EDYCJA: Oto, jak postanowiłem to wdrożyć. Daj mi znać, jeśli są jakieś lepsze sugestie :)

Uświadomiłem sobie, że ta sprawa powinna być naprawdę obsługiwana przez nieruchomość, która posiada Obserwowalne. Oto przykład tego, co chciałbym zrobić:

public class A 
{ 
    private readonly Observable<string> _property; 

    public Observable<string> Property 
    { 
     get { return _property; } 
    } 

    public string Property 
    { 
     set { _property.Value = value; } 
    } 
} 

Oczywiście to się nie kompiluje, ponieważ właściwość jest zdefiniowana dwukrotnie. Oto nieco hackish obejście że myślę definiowania niejawna konwersja w drugą stronę (jak wielu z was sugerowane):

public static implicit operator Observable<T>(T value) 
{ 
    var result = new Observable<T>(); 
    result.SetValueSilently(value); 
    return result; 
} 

i przy użyciu tego nazwać seter przez m.in.:

public Observable<string> Property 
{ 
    get { return _property; } 
    set { _property.Value = value.Value; } 
} 

Odpowiedz

4

Możesz przeciążyć operatora implicit.

public static operator implicit string(YourObject object) 

i pójść w drugą stronę

public static operator implicit YourObject(string s) 

zdawać sobie sprawę, iż jest to bardzo niebezpieczne. Może to prowadzić do tego, że konsumenci klasy będą robić rzeczy, o których nigdy nie pomyślałeś; i pewne zachowanie, które nie ma sensu.

+0

Myślałem o tym, ale tutaj jest problem. Powiedzmy, że wykonuję następujące czynności: [Observable A = new Observable (); Observable B = A; A = "hi";] Teraz A i B nie są zsynchronizowane, ponieważ zamiast ustawiać wartość A, zastąpiliśmy ją nowym obiektem Observable. – hypehuman

+0

Właściwie to zdecydowałem, że to rzeczywiście będzie działać dla mnie. Zmienię moje pytanie, aby wyjaśnić, w jaki sposób. – hypehuman

3

Dodaj kolejny niejawna konwersja, wzdłuż tych linii:

public static implicit operator Observable<T>(T value) 
{ 
    return new Observable<T>{Value = value}; 
} 
4

Jeśli spojrzeć na Overloadable Operators in C#, zobaczysz, że:

operatory przypisania nie może być przeciążona, ale + =, dla przykład, jest oceniany za pomocą +, który może być przeciążony.

można dokonać implicit operator Observable<T>(T value) jednak, które pozwalają niejawnie przekonwertować z T do Observable<T>.

Mimo to nie polecam tego.Wykonywałbym to zadanie wyraźnie, ponieważ wymagałoby to utworzenia każdego nowego wywołania, co spowoduje problemy z procedurami obsługi zdarzeń, ponieważ każde zadanie utworzy nową instancję obiektu.

Powiązane problemy