2008-10-25 16 views
9

Chciałbym zrobić to samo w języku C#. Czy mimo to używasz właściwości w języku C# z parametrami w taki sam sposób, jak przy użyciu parametru "Key" w tym przykładzie VB.NET?Używanie typowych właściwości get get w języku C# ... z parametrami

Private Shared m_Dictionary As IDictionary(Of String, Object) = New Dictionary(Of String, Object) 
Public Shared Property DictionaryElement(ByVal Key As String) As Object 
    Get 
     If m_Dictionary.ContainsKey(Key) Then 
      Return m_Dictionary(Key) 
     Else 
      Return [String].Empty 
     End If 
    End Get 
    Set(ByVal value As Object) 
     If m_Dictionary.ContainsKey(Key) Then 
      m_Dictionary(Key) = value 
     Else 
      m_Dictionary.Add(Key, value) 
     End If 

    End Set 
End Property 

Dzięki

Odpowiedz

14

Czy mimo wykorzystania właściwości w języku C# z parametrami

Nie można tylko dostarczyć domyślny właściwość w C# z argumentem do modelu indeksowanego a ccess (jak w słowniku):

public T this[string key] { 
    get { return m_Dictionary[key]; } 
    set { m_Dictionary[key] = value; } 
} 

Inne właściwości nie mogą mieć argumenty. Zamiast tego użyj funkcji. Przy okazji, zaleca się zrobić to samo w VB, aby inne języki .NET (C# ...) mogły używać twojego kodu.

Przy okazji, Twój kod jest niepotrzebnie skomplikowany. Cztery rzeczy:

  • Nie musisz uciekać przed identyfikatorem String. Użyj bezpośrednio słowa kluczowego.
  • Dlaczego nie używać ""?
  • Użyj TryGetValue, jest to szybciej. Dwa razy wyszukujesz słownik.
  • Twoja selektorka nie musi sprawdzać, czy wartość już istnieje.

Public Shared Property DictionaryElement(ByVal Key As String) As Object 
    Get 
     Dim ret As String 
     If m_Dictionary.TryGetValue(Key, ret) Then Return ret 
     Return "" ' Same as String.Empty! ' 
    End Get 
    Set(ByVal value As Object) 
     m_Dictionary(Key) = value 
    End Set 
End Property 
+1

Miła odpowiedź człowieka. Nie wiem, dlaczego sugerujesz użycie "" zamiast String.Empty chociaż, ... oryginał wydaje mi się bardziej wyraźny. – Stimul8d

+4

@ Stimul8d: Nie śledzę. W jaki sposób '' "' nie jest wyraźny? Jedyną różnicą, jaką widzę pomiędzy tymi dwoma elementami (i tym, IMHO, programista * powinien * zobaczyć), jest to, że 'String.Empty' jest sześć razy dłuższy, dlatego zajmuje sześć razy więcej miejsca i czyta ~ sześć razy więcej sprawia, że ​​kod jest sześć razy gorszy. Dla porównania, to tak jakbyśmy użyli 'Int32.Zero' zamiast' 0'. –

+1

nosed jednorożec: Właśnie użyłem tego samego argumentu w zeszłym tygodniu! –

0

Twój przykładowy kod wydaje mi się bardzo dziwne projektowania i nadużycia, jakie właściwości są przeznaczone. Dlaczego nie po prostu metoda instancji AddOrUpdateKey:

Public Sub AddOrUpdateKey(ByVal Key As String, ByVal Value as Object) 
    If m_Dictionary.ContainsKey(Key) Then 
     m_Dictionary(Key) = Value 
    Else 
     m_Dictionary.Add(Key, Value) 
    End If 
End Sub 

Twoja nieruchomość zwraca również String.Empty jeśli klucz nie istnieje, ale twierdzi, że zwróci Object, ani String.

+0

Witaj Sören, Użycie metody nie pozwala na użycie kodu w następujący sposób: Example.DictionaryElement ["OneKey"] = "Hello world"; Console.WriteLine (Example.DictionaryElement ["OneKey"]); Bardzo dziękuję – Javier

4

"Właściwym" sposobem zrobienia tego w języku C# jest utworzenie klasy potomnej przeznaczonej specjalnie do dostępu do kolekcji. Powinien utrzymywać sam zbiór lub mieć wewnętrzne powiązania z klasą nadrzędną.

3

Oto przykład dla Ciebie (ze zmianami wzdłuż linii sugestie Grauenwolf'S):

using System; 
using System.Collections.Generic; 

public class Test 
{ 
    public FakeIndexedPropertyInCSharp DictionaryElement { get; set; } 

    public Test() 
    { 
     DictionaryElement = new FakeIndexedPropertyInCSharp(); 
    } 

    public class FakeIndexedPropertyInCSharp 
    { 
     private Dictionary<string, object> m_Dictionary = new Dictionary<string, object>(); 

     public object this[string index] 
     { 
      get 
      { 
       object result; 
       return m_Dictionary.TryGetValue(index, out result) ? result : null; 
      } 
      set 
      { 
       m_Dictionary[index] = value; 
      } 
     } 
    } 


} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Test t = new Test(); 
     t.DictionaryElement["hello"] = "world"; 
     Console.WriteLine(t.DictionaryElement["hello"]); 
    } 
} 
0

Dzięki Konrad, Alan, Grauenwolf,

Podsumowując, nie mogę używać C# właściwości dokładnie w taki sam sposób jak w VB.NET ...: _ (W każdym razie twoje odpowiedzi były dla mnie bardzo przydatne, a ja prawdopodobnie wykorzystam te pomysły do ​​mojego kodu C#. pytanie własności, są inne dobre strony.Na przykład,

  • Zastosowanie TryGetValue, to szybciej. Dwa razy wyszukujesz słownik.
  • Twoja selektorka nie musi sprawdzać, czy wartość już istnieje.

Dzięki Sören także, stosując metodę nie pasuje dobrze w moich pierwszych celów, ale dzięki bardzo.

4

bardziej ogólnego przeznaczenia, bezpieczniejsze i wielokrotnego użytku Rozwiązaniem problemu może być wdrożenie rodzajowego, „parametryczne” klasę własności, podobnie jak to:

// Generic, parameterized (indexed) "property" template 
    public class Property<T> 
    { 
     // The internal property value 
     private T PropVal = default(T); 

     // The indexed property get/set accessor 
     // (Property<T>[index] = newvalue; value = Property<T>[index];) 
     public T this[object key] 
     { 
      get { return PropVal; }  // Get the value 
      set { PropVal = value; } // Set the value 
     } 
    } 

Następnie można realizować dowolną liczbę nieruchomości w swoim public class, dzięki czemu klienci mogą ustawić/uzyskać właściwości z indeksem, deskryptor, klucz bezpieczeństwa, czy cokolwiek, na przykład:

public class ParameterizedProperties 
    { 
     // Parameterized properties 
     private Property<int> m_IntProp = new Property<int>(); 
     private Property<string> m_StringProp = new Property<string>(); 

     // Parameterized int property accessor for client access 
     // (ex: ParameterizedProperties.PublicIntProp[index]) 
     public Property<int> PublicIntProp 
     { 
      get { return m_IntProp; } 
     } 

     // Parameterized string property accessor 
     // (ex: ParameterizedProperties.PublicStringProp[index]) 
     public Property<string> PublicStringProp 
     { 
      get { return m_StringProp; } 
     } 
    } 

Wreszcie, kod klienta będzie dostęp „parametrami” właściwości swój publiczny klasa jest tak:

 ParameterizedProperties parmProperties = new ParameterizedProperties(); 
     parmProperties.PublicIntProp[1] = 100; 
     parmProperties.PublicStringProp[1] = "whatever"; 
     int ival = parmProperties.PublicIntProp[1]; 
     string strVal = parmProperties.PublicStringProp[1]; 

Oczywiście, wydaje się to dziwne, ale zdecydowanie działa. Poza tym, z perspektywy kodu klienta, nie jest wcale dziwna - jest prosta i intuicyjna i działa jak prawdziwe nieruchomości. Nie łamie żadnych reguł C#, ani nie jest niezgodny z innymi językami zarządzanymi .NET. Z perspektywy implementatora klas tworzenie ogólnej, "sparametryzowanej" klasy szablonów właściwości do wielokrotnego użytku sprawia, że ​​kodowanie komponentów jest względną bryzą, jak pokazano tutaj.

UWAGA: Zawsze można nadpisać ogólną klasę właściwości, aby zapewnić niestandardowe przetwarzanie, takie jak indeksowane wyszukiwanie, dostęp do właściwości kontrolowanych przez zabezpieczenia lub dowolne, jakie chcesz.

Pozdrawiam!

Mark Jones

+0

+1 Dziękuję Mark, to wygląda dobrze! sprawdzę to – Javier