Использование типичных свойств get set в С#... с параметрами
Я хотел бы сделать то же самое в С#. Есть ли способ использования свойств в С# с параметрами так же, как я сделал с параметром "Ключ" в этом примере VB.NET?
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
Спасибо
Ответы
Ответ 1
Можно ли использовать свойства в С# с параметрами
Нет. Вы можете предоставить свойство по умолчанию в С# с аргументом, чтобы моделировать индексированный доступ (как в словаре):
public T this[string key] {
get { return m_Dictionary[key]; }
set { m_Dictionary[key] = value; }
}
Другие свойства не могут иметь аргументы. Вместо этого используйте функцию. Кстати, он решил сделать то же самое в VB, поэтому другие языки .NET(С#...) могут использовать ваш код.
Кстати, ваш код излишне сложный. Четыре вещи:
- Вам не нужно скрывать идентификатор
String
. Используйте ключевое слово напрямую.
- Почему бы не использовать
""
?
- Используйте
TryGetValue
, это быстрее. Вы дважды запрашиваете словарь.
- Ваш сеттер не должен проверять, существует ли уже существующее значение.
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
Ответ 2
"Правильный" способ сделать это на С# - создать дочерний класс специально для доступа к коллекции. Он должен либо содержать коллекцию, либо иметь внутренние связи с родительским классом.
Ответ 3
Более универсальным, безопасным и многоразовым решением вашей проблемы может быть реализован общий, "параметризованный" класс свойств, например:
// 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
}
}
Затем вы можете реализовать любое количество свойств в своем открытом классе, чтобы клиенты могли устанавливать/получать свойства с помощью индекса, дескриптора, ключа безопасности или чего-то еще, например:
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; }
}
}
Наконец, клиентский код получит доступ к вашим "параметризованным" свойствам открытого класса следующим образом:
ParameterizedProperties parmProperties = new ParameterizedProperties();
parmProperties.PublicIntProp[1] = 100;
parmProperties.PublicStringProp[1] = "whatever";
int ival = parmProperties.PublicIntProp[1];
string strVal = parmProperties.PublicStringProp[1];
Конечно, это кажется странным, но это определенно делает трюк. Кроме того, с точки зрения клиентского кода это не странно - это просто и интуитивно и действует так же, как и реальные свойства. Он не нарушает правил С# и не совместим с другими управляемыми .NET. И с точки зрения реализации класса, создание многоразового, общего, "параметризованного" класса шаблонов свойств делает компонентный кодирование относительным бризом, как показано здесь.
ПРИМЕЧАНИЕ. Вы всегда можете переопределить класс свойств generic для предоставления пользовательской обработки, такой как индексированный поиск, доступ к свойствам с контролем безопасности или что-то еще, что вы хотите.
Ура!
Марк Джонс
Ответ 4
Вот образец для вас (с изменениями в строках предложений 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"]);
}
}
Ответ 5
Ваш образец кода поражает меня как очень странный дизайн и злоупотребление свойствами. Почему не только метод экземпляра 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
Ваше свойство также возвращает String.Empty
, если ключ не существует, но утверждает, что возвращает Object
, а не String
.
Ответ 6
Спасибо Konrad, Alan, Grauenwolf,
В заключение я не могу использовать свойства С# точно так же, как в VB.NET...: _ (Во всяком случае, ваши ответы были очень полезны для меня, и я, вероятно, буду использовать эти идеи для своих С#.
В дополнение к ответам на вопрос о свойствах есть и другие хорошие моменты. Например,
- Используйте TryGetValue, это быстрее. Вы дважды запрашиваете словарь.
- Ваш сеттер не должен проверять, существует ли уже существующее значение.
Спасибо Sören, тоже, используя метод, не очень хорошо соответствует моим первоначальным целям, но очень благодарен.