Использование типичных свойств 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, тоже, используя метод, не очень хорошо соответствует моим первоначальным целям, но очень благодарен.