2015-10-19 43 views
2

我有一些遗留的C#代码与下面的一段:的AddRange让步公共访问列表

private List<MyClass> mList = new List<MyClass>(); 

public List<MyClass> getList() 
{ 
    List<MyClass> list = new List<MyClass>(); 
    list.AddRange(mList); 
    return list; 
} 

不知道是什么的AddRange这里的目的是什么?我可以把它改写为:

public List<MyClass> getList() 
{ 
    return mList; 
} 
+3

是的。从显示的代码中,应该足够了。 –

+4

不完全相同,因为'getList'使用相同的对象创建一个新列表,而'return mList'返回甚至相同的列表。所以如果你要调用getList()。Clear()',原始列表也会被清除。 –

+0

此属性具有丑陋的副作用,因为它意味着您可以通过修改返回的列表来更改拥有类的状态。返回一个“IEnumerable”或者将其作为一种方法是合适的。 – Silvermind

回答

5

如果单纯使用return mlist,你返回mlist实例,而原来的代码返回它的一个浅拷贝。


说你的类如下所示:

class Foo 
{ 
    public Foo() 
    { 
     mList.Add(1); 
    } 

    private List<int> mList = new List<int>(); 

    public List<int> getList() 
    { 
     List<int> list = new List<int>(); 
     list.AddRange(mList); 
     return list; 
    } 
} 

现在你运行

var x = new Foo(); 
x.getList().Add(2); 
x.getList().Add(3); 

mList内容仍然是一个1,因为getList调用返回副本mList,而不是列表本身。

如果更改就像你在你的问题做了代码,你会改变mList现在将包含的元素123


这不是从一个副本返回方法的名称清楚,所以你也许希望将它更改为类似GetListCopy(在这种情况下,该方法可以简单地返回new List<MyClass>(mList)mList.ToList()),或返回列表,一个IReadOnlyList表明不应该更改列表。

public IReadOnlyCollection<MyClass> getList() 
{ 
    return mList.AsReadOnly(); 
} 
+1

这个没啥解释 –

+0

@TimSchmelter你觉得怎么解释不了?原始代码返回列表的副本,新代码返回'mList'实例。 – sloth

+2

OP似乎并不熟悉C#并提出一个基本问题。因此,回答它返回一个浅拷贝而不是原始列表可能是正确的,但如果OP不知道它的意思,它不是很有帮助。何时重要/有所作为? (如果你调用Clear()') –

0

不,你不能。 这可能会导致您的软件出现一些意外行为,因为代码就像创建一个List的新实例,并且您的解决方案每次调用该方法时都会返回相同的实例。

2

正如已经指出的那样,如果您只使用return mList;它将返回原始列表而不是其副本。

但是你可以用它简化:

public List<MyClass> getList 
{ 
    return mList.ToList(); // returns copy of original list 
} 
0

这里的唯一目的是克隆原来的列表,以保持不变。 不过,最好是重新写此属性,并把它转化为方法:在源IEnumerable<T>

public List<MyClass> getList() 
{ 
    // note, that Enumerable.ToList() does the same 
    return new List(mList); 
} 

List<T>构造检查ICollection<T>实施,并正确地设置初始容量。由于每次调用都会创建新实例,因此这不应该是属性,而应该是一种方法。

0

蒂姆的评论和懒惰的已经给出了正确的解释。

只是一个额外的点:

private List<MyClass> mList = new List<MyClass>(); 

public List<MyClass> getList1() 
{ 
    List<MyClass> list = new List<MyClass>(); 
    list.AddRange(mList); 
    return list; 
} 

public List<MyClass> getList2() 
{ 
    return mList; 
} 

getlis1() -
(1)保持原始列表安全Add()AddRange()Clear()不会影响它。
(2)抛出如果mList为空,则为异常!

getlis2() -
(1)公开原始列表mListAdd()AddRange()Clear()影响(修改)它。
(2)如果mList为空,则返回null