ConcurrentDictionary.GetOrAdd (): valueFactory с другой подписью - PullRequest
1 голос
/ 10 февраля 2011

У меня есть ConcurrentDictionary:

private static ConcurrentDictionary<int, string> _cd = new ConcurrentDictionary<int, string>();

Чтобы быть консервативным, фактический ключ, который будет использоваться для извлечения элементов, является объектом, но вместо этого я просто использую его хэш-код в качестве ключа, чтобы (потенциально большой) объект не являлся ключом:

public static string GetTheValue(Foo foo)
{
    int keyCode = foo.GetHashCode(); // GetHashCode is overridden to guarantee uniqueness

    string theValue = _cd.GetOrAdd(keyCode, FooFactory);

    return theValue;
}

Однако при подготовке объекта на фабрике мне нужны различные свойства объекта Foo:

private static string FooFactory(Foo foo)
{
    string result = null;

    object propA = foo.A;
    object propB = foo.B;

    // ... here be magic to set result

    return result;
}

Поскольку параметр valueFactory функции GetOrAdd () ожидает Func<int, string>, выясняется, что я не могу передать ему свой объект Foo. Можно ли вообще это сделать?

Ответы [ 3 ]

3 голосов
/ 10 февраля 2011

Нет ничего плохого в использовании большого объекта в качестве ключа.

Если объект не является struct (и не должен быть структурой), он никогда не будет скопирован.
вы намерены иметь возможность искать вещи позже, ваш объект, очевидно, будет зависать, поэтому у вас не будет утечек памяти.реализации, не будет никакого влияния на производительность.

2 голосов
/ 10 февраля 2011

Я думаю, что здесь есть фундаментальное недоразумение:

Чтобы быть консервативным , фактический ключ, который будет использоваться для извлечения элементов, является объектом, но я вместо этого просто использую его хешкод в качестве ключа , так что (потенциально большой) объект не является ключом .

Я выделил фразы, которые I считают Вы думаете, что связаны.Они действительно нет.Если вы представляете свой словарь слишком большим, потому что его ключи - это большие объекты, вы неправильно его представляете.Для ссылочных типов (любые class в C #) ключи будут храниться в словаре только как ссылки , которые являются размером целого числа.И если вы беспокоитесь о передаче ключей между методами, опять же: это не то, что вы думаете.Будут скопированы и переданы только ссылки, а не сами объекты.

Поэтому я согласен с SLaks : просто используйте ваш тип Foo (или как он там на самом деле называется) в качестве ключа впервое место.Это сделает вашу жизнь намного проще.

0 голосов
/ 24 августа 2016

Мне нужно это по другой причине. Если кто-то еще окажется здесь, как я, вот как это можно сделать:

public static string GetTheValue(Foo foo)
{
    int keyCode = ...

    string theValue = _cd.GetOrAdd(keyCode, (key => FooFactory(foo))); //key is not used in the factory

    return theValue;
}
...