Frage

Ich würde das Gleiche in C#tun. Gibt es sowieso die Verwendung von Eigenschaften in C# mit Parametern auf die gleiche Weise, wie ich es mit dem Parameter -Schlüssel in diesem Beispiel für VB.NET gemacht habe?

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

Vielen Dank

War es hilfreich?

Lösung

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

Nein, Sie können das nur zur Verfügung stellen Ursprünglich Eigenschaft in C# mit einem Argument, um den indizierten Zugriff zu modellieren (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 ist es 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 dem nicht entkommen String Kennung. Verwenden Sie das Schlüsselwort direkt.
  • Warum nicht benutzen ""?
  • Verwenden TryGetValue, es ist schneller. Sie befragen das Wörterbuch zweimal.
  • Ihr Setter 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

Andere Tipps

Der "richtige" Weg, dies in C# zu tun, besteht darin, die untergeordnete Klasse speziell für den Zugriff auf die Sammlung zu erstellen. Es sollte entweder die Sammlung selbst aufbewahren oder interne Verknüpfungen zur übergeordneten Klasse haben.

Eine allgemeinere, sicherere und wiederverwendbare Lösung für Ihr Problem kann eine generische, "parametrisierte" Eigenschaftsklasse wie folgt implementieren:

    // 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 können dann eine beliebige Anzahl von Eigenschaften in Ihrer öffentlichen Klasse implementieren, damit die Kunden die Eigenschaften mit einem Index, einem Deskriptor, einem Sicherheitsschlüssel oder was auch immer feststellen können:

    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 würde der Client -Code auf die "parametrisierten" Eigenschaften Ihrer öffentlichen Klasse 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 macht definitiv den Trick. Außerdem ist es aus Sicht der Client-Code überhaupt nicht seltsam-es ist einfach und intuitiv und wirkt wie echte Eigenschaften. Es brechen weder C# -Regeln, noch ist es mit anderen .NET -verwalteten Sprachen nicht kompatibel. Und aus der Perspektive des Klasse-Implementers macht das Erstellen einer wiederverwendbaren, generischen, "parametrisierten" Eigenschaftsvorlagenklasse die Komponenten eine relative Brise, wie hier gezeigt.

Hinweis: Sie können die generische Eigenschaftsklasse jederzeit überschreiben, um eine benutzerdefinierte Verarbeitung bereitzustellen, wie z. B. indexierte Suche, Sicherheitssteuerungszugriff oder alles, was Sie möchten.

Prost!

Mark Jones

Hier ist ein Beispiel für Sie (mit Änderungen nach den Vorschlägen von Grauenwolf):

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"]);
    }
}

Ihr Code -Beispiel fällt mir als ein sehr seltsames Design und einen Missbrauch darüber an, wofür Eigenschaften gedacht sind. Warum nicht nur eine Instanzmethode? 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 Immobilie kehrt auch zurück String.Empty Wenn der Schlüssel nicht existiert, aber behauptet, eine zurückzugeben Object, Noch a String.

Danke Konrad, Alan, Grauenwolf,

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

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

  • Verwenden Sie TrygetValue, es ist schneller. Sie befragen das Wörterbuch zweimal.
  • Ihr Setter muss nicht testen, ob der Wert bereits existiert.

Vielen Dank auch, dass Sören mit einer Methode nicht gut in meine ersten Ziele passt, aber vielen Dank.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top