C#通用列表混淆 [英] C# Generic List Confusion
问题描述
我以为我理解了C#中的泛型,直到我对以下简单代码感到震惊:
I thought I understood generics in C#, until I got something of a shock with the following simple code:
List<Tuple<int,string>> list = new List<Tuple<int,string>>();
list.Add( new Tuple<int,string>( 1, "abc" ) );
list.Add( new Tuple<int,string>( 2, "def" ) );
list.Add( new Tuple<int,string>( 3, "ghi" ) );
list[ 0 ].Item1 = 4;
编译器错误:错误CS0200:属性或索引器'System.Tuple< int,string> .Item1'无法分配 - 它是只读的
我不得不说,我不明白为什么。在这种情况下,我正在分配一个整数,所以它必须在堆中的某个地方留出4个字节,所以为什么我不能分配给它呢?即使我尝试分配字符串,元组也会保存对字符串的引用,这两个字符串都在堆上分配,所以为什么我不能重新分配它呢?
困惑,我以为我会使用我自己的结构来解决这个问题,如下所示:
Compiler Error: error CS0200: Property or indexer 'System.Tuple<int,string>.Item1' cannot be assigned to -- it is read only
I have to say, I don't understand why. In this case, I am assigning an integer, so it must have 4 bytes set aside for it somewhere in the heap, so why can't I assign to it? Even if I tried to assign the string, the tuple holds a reference to a string, both of which are allocated on the heap, so again why can't I re-assign it?
Puzzled, I thought I'd work around the problem using a struct of my own as follows:
private struct Foo
{
public Foo( int i, string s )
{
_position = i;
_name = s;
}
public int Position
{
get { return _position; }
set { _position = value; }
}
public string Name
{
get { return _name; }
set { _name = value; }
}
private int _position;
private string _name;
}
List<Foo> list = new List<Foo>();
list.Add( new Foo( 1, "abc" ) );
list.Add( new Foo( 2, "def" ) );
list.Add( new Foo( 3, "ghi" ) );
list[ 0 ].Position = 4;
编译错误:错误CS1612:无法修改'System.Collections.Generic.List< Foo> .this [int]'的返回值,因为它不是变量
这个错误消息我真的不明白。我可能会想到这方面的解决方法,但我不得不说我不确定我明白我做错了什么。
任何帮助或指向好的指针我们将非常感激地收到这篇文章。
亲切的愿望~Patrick
Compiler error: error CS1612: Cannot modify the return value of 'System.Collections.Generic.List<Foo>.this[int]' because it is not a variable
This error message I really didn't understand. I can probably think of workarounds for this, but I have to say that I'm not sure I understand what I am doing wrong.
Any help or pointers to good articles on this would be gratefully received.
Kind wishes ~ Patrick
推荐答案
两个问题:
首先:元组
是只读对象,它们的值只能在构造函数中设置。
http://msdn.microsoft.com/en -us / library / system.tuple(v = vs.100).aspx [ ^ ]
第二名:你的Foo
是struct
因此它具有值语义。
价值语义 [ ^ ]
如果更改Foo
是一个类
而不是struct
你会得到你期望的行为。
Two issues:
First:Tuple
s are read-only objects, their values can be set only in the constructor.
http://msdn.microsoft.com/en-us/library/system.tuple(v=vs.100).aspx[^]
Second: YourFoo
is astruct
thus it has value semantics.
Value semantics[^]
If you changeFoo
to be aclass
instead ofstruct
you'll get the behavior you're expecting.
此问题与泛型无关,与集合无关。它与一个非常简单的事情有关:属性可以是只读的,当只为属性定义了一个getter而不是一个setter时就会发生这种情况,就像Tuple
。请从这里开始:
http:// msdn.microsoft.com/en-us/library/x9fsa0sw%28v=vs.110%29.aspx [ ^ ]。
实际上,你们所有人需要是:
This problem is not related to generics and not related to collections. It's related to a very simple thing: properties can be read-only, which happens when only a getter is defined for a property, and not a setter, as in the case ofTuple
. Please start here:
http://msdn.microsoft.com/en-us/library/x9fsa0sw%28v=vs.110%29.aspx[^].
Practically, all you need is this:
list[0] = new Tuple<int,string>(4, list[0].Item2);
只是想提一下你在Tuples,KeyValuePairs上会有相同的行为, ..当然还有匿名类型。例如:
Just want to mention that you will have the same behaviour on Tuples, KeyValuePairs, .. and of course also on anonymouse types. example:
List<dynamic> list = new List<dynamic>();
list.Add(new { Position = 1, Name = "abc" });
list.Add(new { Position = 2, Name = "def" });
list.Add(new { Position = 3, Name = "gah" });
list[0] = new { Position = 1, Name = "xxx" };
// not list[0].Name = "xxx"; :-(
Console.WriteLine(list[0].Name);
SA提到它 - 它与仿制药没有什么共同点,只是属性Setters在这些情况下缺失...(不要用反射来破坏周围环境,使用适当的设计(使用参考类型)
SA mentioned it - it has nothing todo with the generics, just the property Setters are missing in these cases... (don't hack arround with reflection to circumvent it, use a proper desing (by using a reference type)
这篇关于C#通用列表混淆的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!