Zrozumienie Uwarunkowań

Próbuję zrozumieć ConditionalWeakTable . Jaka jest różnica między

class ClassA
{
    static readonly ConditionalWeakTable<ClassA, OtherClass> OtherClassTable
        = new ConditionalWeakTable<ClassA, OtherClass>();
}

I

class ClassB
{
    OtherClass otherClass;
}

? Jakie byłyby plusy i minusy używania ClassA lub ClassB do odwoływania się do pola nullable?

Author: cm007, 2013-08-27

3 answers

Nie do końca rozumiem, o co pytasz, zakładam, że pytasz, czy powinieneś używać właściwości wewnątrz swojego typu, czy ConditionalWeakTable, do których możesz dołączyć taką właściwość dla danej instancji typu. Jeśli tak, możesz alternatywnie zapytać, czy powinieneś używać samej właściwości versus dictionary, która może zawierać tę właściwość pod określonym kluczem(który będzie twoją konkretną instancją typu). Chyba, że potrzebujesz takiego słownika, to całkiem nonsens.

Zrozumienie ConditionalWeakTable<TKey, TValue>:

To, co ConditionalWeakTable w rzeczywistości pozwala na dołączanie dodatkowych informacji do istniejących, zarządzanych, nie dynamicznych obiektów CLR. Zasadniczo może być rozumiany jako słownik, w którym zarówno klucze, jak i wartości są słabo odwołane, a wartość jest utrzymywana przy życiu tak długo, jak klucz jest żywy. Więcej informacji można znaleźć na MSDN.

Powinieneś więc zadać sobie pytanie, Jakie są Twoje potrzeby. Zakładając, że Twoje typy to instancja:
var classA = ClassA(); 
var classB = ClassB(); 
var other = OtherClass();

Czy chcesz użyć właściwości binded do takich instancji w ten sposób:

/* set */
var other = new OtherClass();        
ClassA.OtherClassTable.Add(classA, other);
/* get */
OtherClass data = null;
var result = ClassA.OtherClassTable.TryGetValue(classA, out data);

Zamiast tego poniżej?

/* set */
classB.OtherClass = other;
/* get */
var result = classB.OtherClass;

Jeśli nie mają szczególnych potrzeb, odpowiedź wydaje się być dość oczywiste. Są oczywiście dalsze kwestie tutaj:

Co to jest słabe odniesienie i dlaczego chcesz go używać?

Ten MSDN artykuł krótko wyjaśnia temat. W zasadzie mówi, że słabe referencje nie rozszerzają czas życia obiektu, pozwalając mu na zbieranie śmieci, po osiągnięciu takiego obiektu przez kod aplikacji. Słabe odniesienia mogą być przydatne do wskazywania obiektów, które powinny być dostępne dla GC, jeśli nie są aktywnie używane. Jeśli jednak program używa dużej liczby małych obiektów, słabe odwołania mogą negatywnie wpłynąć na zużycie pamięci. Wątki takie jak this i this powinny również wyjaśnić niektóre pozostałe wątpliwości.

Jeśli szukasz przykład, kiedy można użyć ConditionalWeakTable<TKey, TValue> zamiast standardowego Dictionary<TKey, TValue>, wyobraź sobie następujący przypadek. Chcesz powiązać słownik właściwości z instancją i w czasie wykonywania, ale jednocześnie nie chcesz uniemożliwiać ich gromadzenia, jeśli przestałeś ich aktywnie używać. Niestety w standardowym podejściu jest to niemożliwe - GC jest zablokowane, ponieważ słownik nadal posiada silne odniesienia do nich, jak to: {]}

var x = new object();
x.Props().Y = "hello";

static class ExpandoExtensions 
{
    private static IDictionary<object, dynamic> props = 
        new Dictionary<object, dynamic>();
    public static dynamic Props(this object key)
    { 
        dynamic o;
        if (!props.TryGetValue(key, out o)){
            o = new ExpandoObject();
            props[key] = o;
        }
        return o;       
    } 
}

Oczywiście zawsze można je zdjąć ręcznie, ale czy nie jest to podejście pokazane poniżej?

static class ExpandoExtensions
{
    private static readonly ConditionalWeakTable<object, ExpandoObject> props =
        new ConditionalWeakTable<object, ExpandoObject>();

    public static dynamic Props(this object key)
    { 
        return props.GetOrCreateValue(key);       
    } 
}

At the same time ( MSDN )

Unikaj używania słabych odniesień jako automatycznego rozwiązania pamięci problemy z zarządzaniem. Zamiast tego opracuj skuteczną politykę buforowania dla obsługa obiektów aplikacji.

Te metody rozszerzenia pokazane powyżej są zaczerpnięte z tego wątku.

 32
Author: jwaliszko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:31

Największą różnicą między tymi dwoma--rzeczywiście, głównym powodem, dla którego ConditionalWeakTable istnieje i powodem, dla którego jest częścią CompilerServices -- jest dodanie pola do ClassA wymaga możliwości dodania pola do ClassA, ale konstruowanie ConditionalWeakTable z kluczem typu ClassA nie robi. Efektywnie, ConditionalWeakTable istnieje, aby Kod mógł efektywnie "dodać pole" do instancji dowolnej klasy bez konieczności modyfikowania samej klasy . Choć w wielu przypadkach może być możliwe użycie tożsamości slabe-key dictionary for such a purpose, that would work as long as no value held a direct or indirect reference to its key, and there were no cycles of keys which been referred directly or directly via other key ' s values. Konstrukcja ConditionalWeakTable pozwala na zbieranie kluczy i wartości nawet wtedy, gdy takie cykle istnieją.

 8
Author: supercat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-12 17:22:37

Zaletą pierwszego podejścia jest możliwość buforowania instancji OtherClass. Na przykład,

class ClassA
{
    static readonly ConditionalWeakTable<ClassA, OtherClass> OtherClassTable
        = new ConditionalWeakTable<ClassA, OtherClass>();

    public void Attach(OtherClass otherClass)
    {
        OtherClassTable.Add(this, otherClass);
    }

    public bool Get(out OtherClass otherClass)
    {
        return OtherClassTable.TryGetValue(this, out otherClass);
    }
}

Następnie możesz dołączyć instancję OtherClass do instancji ClassA. Instancja OtherClass będzie przechowywana w pamięci tak długo, jak instancja ClassA, do której jest dołączona, jest utrzymywana przy życiu.

 1
Author: cubetwo1729,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-03 19:34:18