2008-10-25 10 views
9

Ich möchte das gleiche in C# tun. Gibt es sowieso Eigenschaften in C# mit Parametern auf die gleiche Weise, die ich mit dem Parameter 'Key' in diesem VB.NET-Beispiel getan habe?Verwenden der typischen GetSet-Eigenschaften in C# ... mit Parametern

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 

Dank

Antwort

14

Gibt es trotzdem die Verwendung von Eigenschaften in C# mit Parametern

Nein, Sie nur die Standard Eigenschaft in C# zur Verfügung stellen können mit einem Argument, um ein indexiertes a zu modellieren ccess (wie in einem Wörterbuch):

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

Andere Eigenschaften können keine Argumente haben. Verwenden Sie stattdessen eine Funktion. Übrigens, es wird empfohlen, dasselbe in VB zu tun, damit andere .NET-Sprachen (C# ...) Ihren Code verwenden können.

Übrigens ist Ihr Code unnötig kompliziert. Vier Dinge:

  • Sie müssen nicht die String Kennung entgehen. Verwenden Sie das Schlüsselwort direkt.
  • Warum nicht "" verwenden?
  • Verwenden Sie TryGetValue, es ist schneller. Sie fragen das Wörterbuch zweimal ab.
  • Ihr Setzer muss nicht testen, ob der Wert bereits existiert.

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

Schöne Antwort Mann. Ich weiß nicht, warum Sie vorschlagen "" anstelle von String.Empty, aber ... das Original scheint mir expliziter. – Stimul8d

+4

@ Stimul8d: Ich folge nicht. Wie ist '' '' nicht explizit? Der einzige Unterschied, den ich zwischen den beiden sehe (und das, IMHO, ein Programmierer * sollte * sehen) ist, dass 'String.Empty' sechsmal länger ist, daher braucht es sechsmal mehr Speicherplatz und dauert ~ sechsmal länger, um es zu lesen es macht den Code sechsmal schlimmer. Zum Vergleich: Als würden wir 'Int32.Zero' anstelle von' 0' verwenden. –

+1

gerochenes Einhorn: Ich habe letzte Woche das gleiche Argument benutzt! –

0

Ihr Codebeispiel scheint mir ein sehr seltsames Design und einen Missbrauch, welche Eigenschaften für bestimmt sind. Warum nicht nur eine Instanz Methode 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 

Ihre Eigenschaft auch wieder String.Empty, wenn der Schlüssel nicht existiert, sondern beansprucht ein Object zurückzukehren, noch ein String.

+0

Hallo Sören, Die Verwendung einer Methode erlaubt mir nicht, den Code auf diese Weise zu verwenden: Example.DictionaryElement ["OneKey"] = "Hallo Welt"; Console.WriteLine (Example.DictionaryElement ["OneKey"]); Vielen Dank – Javier

4

Der "richtige" Weg, um es in C# zu tun ist, Kind-Klasse speziell für den Zugriff auf die Sammlung zu erstellen. Es sollte entweder die Sammlung selbst enthalten oder interne Verknüpfungen mit der übergeordneten Klasse haben.

3

ist hier eine Probe für Sie (mit Änderungen entlang der Linien von Grauenwolf Vorschläge):

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

Dank Konrad, Alan, Grauenwolf,

Abschließend kann ich nicht genau C# Eigenschaften verwenden genauso wie in VB.NET ...: _ (Wie auch immer, deine Antworten waren sehr nützlich für mich, und ich werde diese Ideen wahrscheinlich zu meinem C# Code bringen.

Zusätzlich zu den Antworten auf die Eigenschaften Frage, gibt es andere gute Punkte.Zum Beispiel

  • Verwenden TryGetValue, dann ist es schneller. Sie fragen das Wörterbuch zweimal ab.
  • Ihr Setzer muss nicht testen, ob der Wert bereits existiert. nicht paßt gut in meinen ursprünglichen Zielen

Dank Sören auch tun mit einem Verfahren, aber dank sehr viel.

4

Ein Allzweck-, sicherer und wiederverwendbare Lösung für Ihr Problem könnte eine generische „parametrisiert“ Festigkeitsklasse, wie diese Umsetzung sein:

// 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 
     } 
    } 

Sie dann eine beliebige Anzahl von Eigenschaften implementieren könnte in Ihrem public class so dass die Kunden könnten eingestellt/die Eigenschaften mit einem Index erhalten, Beschreiber, Sicherheitsschlüssel oder was auch immer, wie folgt aus:

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; } 
     } 
    } 

Schließlich Client-Code würde Ihre öffentlichen Klasse „parametrisiert“ Eigenschaften wie folgt zugreifen:

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

Sicher, das scheint seltsam, aber es ist definitiv der Trick. Außerdem ist es aus einer Client-Code-Perspektive überhaupt nicht seltsam - es ist einfach und intuitiv und verhält sich genau wie echte Eigenschaften. Es bricht keine C# -Regeln und ist auch nicht mit anderen von .NET verwalteten Sprachen kompatibel. Und aus Sicht des Klassenimplementierers macht das Erstellen einer wiederverwendbaren, generischen, "parametrisierten" Eigenschaftsvorlagenklasse die Komponentencodierung relativ einfach, wie hier gezeigt.

ANMERKUNG: Sie können die generische Eigenschaftsklasse jederzeit überschreiben, um benutzerdefinierte Verarbeitung bereitzustellen, z. B. indizierte Suche, Zugriff auf sicherheitsgesteuerte Eigenschaften oder was immer Sie wollen.

Prost!

Mark Jones

+0

+1 Danke Mark, das sieht gut aus! Ich werde das überprüfen – Javier

Verwandte Themen