2017-10-13 15 views
3

比方说,我有一个类的字符串属性将字符串属性添加为字典的关键字克隆字符串?有没有适当的解决方法?

public class Something 
{ 
    public int SomeIntProperty { get; set; } 
    public string SomeStringProperty { get; set; } 
} 

,让我们说,SomeStringProperty可以均是很长,我想创建一个字典

this.dic = somethings 
    .GroupBy(s => s.SomeStringProperty) 
    .ToDictionary(g => g.Key); 

,我在记忆保持我的应用程序运行的持续时间。我的问题是,由于字符串像值类型一样行为,最终会重复字典中的字符串。如果是这样,什么是解决方法,以便我可以保持对字符串的引用或压缩/散列/等。他们?

回答

3

我的问题是,由于字符串的行为方式类似于值类型,是否最终会重复字典中保存的字符串?

C#中的字符串不是值类型,它们当然不会像一个类似的行为。

C#字符串是不可变的,这使得它们适合用作关联容器中的键。但是,使用字符串作为关键字或以任何其他身份使用,不会导致克隆其内容。

您可以通过检查源数组的SomeStringProperty的字典关键字的引用相等性来验证是否正在进行克隆。字典中的每个键将存在于源阵列中:

var data = new[] { 
    new Something {SomeIntProperty=1, SomeStringProperty="A"} 
, new Something {SomeIntProperty=2, SomeStringProperty="A"} 
, new Something {SomeIntProperty=3, SomeStringProperty="A"} 
, new Something {SomeIntProperty=4, SomeStringProperty="A"} 
, new Something {SomeIntProperty=5, SomeStringProperty="A"} 
, new Something {SomeIntProperty=6, SomeStringProperty="B"} 
, new Something {SomeIntProperty=7, SomeStringProperty="B"} 
, new Something {SomeIntProperty=8, SomeStringProperty="C"} 
, new Something {SomeIntProperty=9, SomeStringProperty="D"} 
}; 
var dict = data.GroupBy(s => s.SomeStringProperty) 
        .ToDictionary(g => g.Key); 
foreach (var key in dict.Keys) { 
    if (data.Any(s => ReferenceEquals(s.SomeStringProperty, key))) { 
     Console.WriteLine("Key '{0}' is present.", key); 
    } else { 
     Console.WriteLine("Key '{0}' is not present.", key); 
    } 
} 

上述代码打印

Key 'A' is present. 
Key 'B' is present. 
Key 'C' is present. 
Key 'D' is present. 

Demo.

1

由于该串像值类型的方式

字符串不是值类型,它们是不可变的参考类型。

,将最终复制串在字典

错了,你最终只会产生新的字符串,如果你尝试修改他们举行。那么将会创建一个包含新内容的新字符串。

1

该文档描述了由价值,这是在这种情况下误导性,因为,虽然该字符串是不可改变通过变量String,运行时保持原始值直到我们改变它参考。

所以,即使LINQ的ToDictionary()方法传递字符串作为参数来Dictionary.Add()under the hood,既SomeStringPropertyDictonary关键点到相同的位置在存储器中。

但是,如果我们要改变的关键选择的字符串:

.ToDictionary(g => g.Key + "changed!"); 

...那么运行时将复制原始字符串值来创建新的密钥。

我们可以验证的参考是相同的:

var first = this.dict.First(); 
Console.WriteLine(object.ReferenceEquals(first.Key, first.Value.SomeStringProperty)); 

This article确实说明在C#String对象的细微差别非常出色。

+0

很简洁的解释。另请参阅:[这个答案](https://stackoverflow.com/questions/10792603/how-are-strings-passed-in-net) –

相关问题