C#通用列表混淆 [英] C# Generic List Confusion

查看:131
本文介绍了C#通用列表混淆的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我以为我理解了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: Tuples 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: Your Foo is a struct thus it has value semantics.
Value semantics[^]
If you change Foo to be a class instead of struct 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 of Tuple. 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);



-SA


只是想提一下你在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆