2011-02-10 20 views
1

我有一個ConcurrentDictionary:ConcurrentDictionary.GetOrAdd():valueFactory有不同的簽名

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; 
} 

由於GetOrAdd()的valueFactory參數需要Func<int, string>,因此看起來我無法將我的Foo對象傳遞給它。是否可以這樣做?

+2

不這樣做。哈希碼不是唯一的。你應該使用大對象;它不會造成任何傷害。 – SLaks 2011-02-10 15:27:09

+0

@SLaks:假設我使用ToString()而不是GetHashCode()。 – Bullines 2011-02-10 15:29:16

回答

2

我認爲這裏有一個根本性的誤解:

爲保守,以 實際鍵可用於檢索的項目是一個對象 但我不是簡單地使用它的哈希碼 作爲鍵,以便一個(可能是 大)對象不是密鑰

我加粗的是認爲認爲是相關的短語。他們真的不是。如果你認爲你的字典太大了,因爲它的鍵是這些大對象,你想象它是錯的。對於引用類型(C#中的任何class),密鑰將僅以引用存儲在字典中,它們是大量整數的大小。如果您擔心在方法之間傳遞密鑰,那又如何:這不是您的想法。只有引用將被複制並傳遞,而不是對象本身。

所以我同意SLaks:只要使用您的Foo類型(或者其他名稱)作爲首要關鍵。它會讓你的生活變得更簡單。

3

使用大對象作爲鍵沒有任何問題。

除非對象是struct(它不應該是一個結構體),否則它將不會被複制。
如果你打算以後能夠看到,你的對象顯然會停滯不前,所以你不會泄漏內存。

只要您有合理的(或繼承)GetHashCode()Equals()實現,就不會有任何性能影響。

0

我需要這個不同的原因。如果有人像我一樣最終到達這裏,可以這樣做:

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; 
}