提问人:gartenriese 提问时间:4/8/2023 最后编辑:Bill Tür stands with Ukrainegartenriese 更新时间:4/8/2023 访问量:157
IEnumerable 作为构造函数参数,当列表保留在类中时
IEnumerable as constructor parameter when list is kept in class
问:
如果我想将类作为参数传递的列表存储,我应该使用哪种参数类型?
我应该参加 IEnumerable 并执行类似操作吗?但是,如何避免多余的副本呢?如果列表是在构造函数调用中创建的,那肯定是太多了。Items = items.ToList().AsReadOnly()
ToList()
在 C++ 中,我将有一个非引用参数来确保传递列表的副本,但在 C# 中,AFAIK 这是不可能的。
我想到的一个例子是一个事件参数类,它包含一个内容列表,这也是调用类的当前状态。在将列表传递给各种事件处理程序后,列表不应更改。
在构造函数中创建一个副本是可以的,当它被调用时,就像这样:
SomethingHappened?.Invoke(this, new CustomEventArgs(_items));
但是当它被这样调用时,会制作一个不必要的副本:
SomethingHappened?.Invoke(this, new CustomEventArgs(new List { item1, item2 }));
答:
1赞
Julian
4/8/2023
#1
如果不想修改在类中传递给构造函数的列表,则可以将参数定义为 an 并通过调用原始列表来传递它。您仍将使用相同的列表,但会提供一个防止修改的包装器,如文档所示:IReadOnlyList<T>
AsReadOnly()
AsReadOnly()
public class YourClass
{
private IReadOnlyList<SomeType> yourList;
public YourClass(IReadOnlyList<SomeType> list)
{
yourList = list;
}
}
然后调用构造函数,如下所示:
var someList = new List<SomeType>();
var yourClassInstance = new YourClass(someList.AsReadOnly());
您仍然可以更改原始列表引用,它将反映在只读引用中,因为它们实际上访问的是同一个列表,但您将无法修改其中的列表。YourClass
或者,如果不能在外部调用,则需要在构造函数中调用它,这在技术上允许类在存储只读引用之前进行修改:AsReadOnly()
public class YourClass
{
private IReadOnlyList<SomeType> yourList;
public YourClass(IList<SomeType> list)
{
yourList = list.AsReadOnly();
}
}
如果您确实需要修改传递的列表,则需要创建一个副本,然后通过该副本获得副本的所有权:YourClass
public class YourClass
{
private IList<SomeType> yourList;
public YourClass(IList<SomeType> list)
{
yourList = new List<T>(list);
}
}
由于被调用方无法自行知道是否应创建副本,因此可以向构造函数添加一个可选标志,以将责任转移给调用方:
public class YourClass
{
private IList<SomeType> yourList;
public YourClass(IList<SomeType> list, bool makeCopy = false)
{
yourList = makeCopy ? new List<T>(list) : list;
}
}
这样,调用方必须决定是否需要副本:
var someList = new List<SomeType>();
//Make a copy explicitly
var yourClassInstance1 = new YourClass(someList, true);
//Do not make a copy
var yourClassInstance2 = new YourClass(new List<SomeType>{ object1, object2 });
评论
0赞
gartenriese
4/8/2023
谢谢,我希望会有更好的解决方案,但我想我只是被使用 C++ 宠坏了。
1赞
Julian
4/8/2023
@gartenriese我不知道针对类对象的这个特定问题有另一种解决方案。没有参数(在 C# 中,关键字是编译时关键字),也不能通过将引用类型实例作为值传递来隐式创建引用类型实例的副本。这仅适用于值类型,例如结构。const
const
评论
IReadOnlyList<T>
AsReadOnly()