9

C#でも同じことをしたいです。この VB.NET の例でパラメータ 'Key' を使用したのと同じ方法で、C# でパラメータを使用してプロパティを使用する方法はありますか?

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

ありがとう

4

6 に答える 6

14

パラメータを使用してC#でプロパティを使用する方法はありますか

いいえ。インデックス付きアクセスをモデル化するために、引数を使用して C# でデフォルトプロパティを指定することしかできません(辞書のように)。

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

他のプロパティには引数を指定できません。代わりに関数を使用してください。ちなみに、他の .NET 言語 (C# など) でコードを使用できるように、VB で同じことを行うことをお勧めします。

ところで、あなたのコードは不必要に複雑です。4 つのこと:

  • String識別子をエスケープする必要はありません。キーワードを直接使用します。
  • なぜ使用しないの""ですか?
  • を使用TryGetValueしてください。より高速です。ディクショナリを 2 回クエリします。
  • セッターは、値が既に存在するかどうかをテストする必要はありません。

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
于 2008-10-25T15:05:37.520 に答える
4

C# でこれを行う「適切な」方法は、特にコレクションにアクセスするための子クラスを作成することです。コレクション自体を保持するか、親クラスへの内部リンケージを持つ必要があります。

于 2008-10-25T17:35:45.437 に答える
4

問題に対するより汎用的で、より安全で再利用可能な解決策は、次のような汎用の「パラメータ化された」プロパティ クラスを実装することです。

    // 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];

確かに、これは奇妙に思えますが、間違いなくうまくいきます。さらに、クライアント コードの観点からは、これはまったく奇妙ではありません。単純で直感的で、実際のプロパティのように機能します。C# の規則に違反することはなく、他の .NET マネージ言語と互換性がないこともありません。また、クラス実装者の観点から見ると、ここに示すように、再利用可能で汎用的な「パラメーター化された」プロパティ テンプレート クラスを作成すると、コンポーネントのコーディングが比較的簡単になります。

注: いつでもジェネリック プロパティ クラスをオーバーライドして、インデックス付きルックアップ、セキュリティ制御されたプロパティ アクセス、または必要なものすべてなどのカスタム処理を提供できます。

乾杯!

マーク・ジョーンズ

于 2011-06-11T00:55:36.237 に答える
3

これがあなたのためのサンプルです(グラウエンウルフの提案に沿った変更があります):

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"]);
    }
}
于 2008-10-25T19:13:16.503 に答える
0

ありがとう、コンラッド、アラン、グラウエンウルフ、

結論として、VB.NET とまったく同じ方法で C# プロパティを使用することはできません... :_( とにかく、あなたの答えは私にとって非常に役に立ちました。おそらく、このアイデアを私の C# コードに取り入れます。

プロパティの質問への回答に加えて、他にも良い点があります。例えば、

  • TryGetValue を使用してください。より高速です。ディクショナリを 2 回クエリします。
  • セッターは、値が既に存在するかどうかをテストする必要はありません。

Sören にも感謝します。メソッドを使用することは、私の最初の目的にはうまく適合しませんが、どうもありがとうございました。

于 2008-10-26T15:52:18.687 に答える
0

あなたのコードサンプルは、非常に奇妙なデザインであり、プロパティが意図されているものを悪用しているように思えます。インスタンスメソッドだけではない理由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ます。

于 2008-10-25T15:11:33.417 に答える