Verwenden der typischen Get -Set -Eigenschaften in C#… mit Parametern
-
04-07-2019 - |
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
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.