11

C#チームは以前、拡張プロパティやイベントなどをC#に追加することを検討していました。

エリック・リッパートによる:

http://blogs.msdn.com/b/ericlippert/archive/2009/10/05/why-no-extension-properties.aspx

ただし、これらの機能を使用するには、オブジェクトを使用して新しい種類の状態を格納できる必要があります。これを行う唯一の方法は、辞書を使用して、オブジェクトの各インスタンスを追加の状態に関連付けることだと思われます。

独自の辞書(およびおそらくget / set拡張メソッド)を作成することにより、この機能を「手動で」コピーできると便利です。ただし、オブジェクトの特定のインスタンスを特定の状態に関連付けるには、オブジェクトへの実際の参照をハッシュする必要があります。別の言語では、メモリの場所をハッシュすることでこれを行うことができますが、C#では一定であることが保証されておらず、安全でないコードを使用してこの機能を実現することは、とにかく理想からはほど遠いです。

オブジェクトの内部状態が変化しても変化しないオブジェクトへのハッシュ可能な参照を取得できるかどうか誰かが知っていますか?明らかに、メモリの場所に関係なく個々のオブジェクトを追跡するための内部メカニズムがいくつかありますが、それがユーザーコードに公開されているかどうかはわかりません。

注:GetHashCode()は、オブジェクトがどのオブジェクトであるかではなく、オブジェクトの内部状態に依存するため、オブジェクト自体をハッシュするだけではまったく機能しません。

洞察をありがとう。

4

2 に答える 2

16

ConditionalWeakTableクラスを探しています。

于 2012-05-18T14:55:18.537 に答える
0

** 全体の回答を編集 ** プロパティは、オブジェクトへの弱い参照をキーとして使用するディクショナリと、プロパティとその値を格納するための文字列とオブジェクトのペアを含むディクショナリに保持されます。

オブジェクトのプロパティを設定、取得、または削除するには、オブジェクトをディクショナリの弱参照で検索します。

未使用のプロパティを破棄するには、次の 2 つの方法があります。

  • 弱参照の IsAlive を確認し、false の場合は辞書のエントリを削除します
  • 「拡張可能な」オブジェクトに IDisposable を実装し、破棄されるオブジェクトのプロパティを削除する拡張メソッドを呼び出します。

サンプル コードにオプションの using ブロックを含めたので、デバッグして、Dispose がRemoveProperties拡張メソッドを呼び出す方法を確認できます。これはもちろんオプションであり、オブジェクトが GC されたときにメソッドが呼び出されます。

WeakReference、静的辞書、および IDisposable を使用したアイデアの実用的なサンプル。

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
            using (PropertyLessClass plc = new PropertyLessClass())
            {
                plc.SetProperty("age", 25);
                plc.SetProperty("name", "John");
                Console.WriteLine("Age: {0}", plc.GetProperty("age"));
                Console.WriteLine("Name: {0}", plc.GetProperty("name"));
            }
            Console.ReadLine();
        }
    }
}

public class PropertyLessClass : IDisposable
{
    public void Dispose()
    {
        this.DeleteProperties();
    }
}

public static class PropertyStore
{
    private static Dictionary<WeakReference, Dictionary<string, object>> store
        = new Dictionary<WeakReference, Dictionary<string, object>>();

    public static void SetProperty(this object o, string property, object value)
    {
        var key = store.Keys.FirstOrDefault(wr => wr.IsAlive && wr.Target == o);
        if (key == null)
        {
            key = new WeakReference(o);
            store.Add(key, new Dictionary<string, object>());
        }
        store[key][property] = value;
    }

    public static object GetProperty(this object o, string property)
    {
        var key = store.Keys.FirstOrDefault(wr => wr.IsAlive && wr.Target == o);
        if (key == null)
        {
            return null; // or throw Exception
        }
        if (!store[key].ContainsKey(property))
            return null; // or throw Exception
        return store[key][property];
    }

    public static void DeleteProperties(this object o)
    {
        var key = store.Keys.FirstOrDefault(wr => wr.IsAlive && wr.Target == o);
        if (key != null)
        {
            store.Remove(key);
        }
    }
}
于 2012-05-18T15:00:51.733 に答える