我有一个作为Enumerable的字符串集合(例如,假设它是对集合进行某些linq查询的结果)。
IEnumerable<string> myStrings;
以下内容有什么区别
a。
result = myStrings as List<string>;
b。
result = myStrings.ToList();
一个比另一个更有效吗?选项b是否会更改myStrings本身?
答案 0 :(得分:2)
选项a-result=myStrings as List<string>
是一种安全的类型转换方式,它知道给定类型内部是否包含List<string>
,因此没有多余的内存分配,因为它是类型转换,可以在任何类型/对象上完成。如果类型转换失败,则结果为null
,没有异常,而如果尝试(List<string>) myStrings
,可能会出现异常。
实际上甚至更好的方法-is
运算符myStrings is List<string> result
(称为模式匹配是表达式),它提供布尔结果,如果为true,则会在结果变量(is
中产生有效值运算符已经存在了一段时间,但是使用变量result
进行模式匹配,它跨越了if循环,并且可以在其后的逻辑中使用,这是C#7.1的功能
与此相比:
选项b-result=myStrings.ToList()
是对IEnumerable<T>
的扩展方法调用,它分配并创建新的List<T>
数据结构。这始终是额外的内存分配。以下是Enumerable.ToList()
调用link
public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source) {
if (source == null) throw Error.ArgumentNull("source");
return new List<TSource>(source);
}
答案 1 :(得分:1)
ToList()
是一种方法,它创建List<T>
的新对象。该方法要求集合中的元素为正确的类型。
方法ToList
遍历集合以创建新列表,因此它不仅比强制转换慢,而且更安全,更通用。
由于该方法创建了新列表,因此原始集合的更改不会反映在列表中。
as List<T>
将对象投射到该列表上。这意味着集合必须是List
或从中继承。
当无法将对象投射在null
上时,铸造有时会导致List<T>
由于对象的转换仍保留引用,因此对原始集合的更改将反映在列表中。
更多信息:
ToList()
:
as
:
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/as
答案 2 :(得分:0)
ToList
将创建一个新列表,但对于您而言,由于您引用的是引用类型(字符串),因此新列表将包含对与原始列表相同的对象的引用。
更新新列表中引用的对象的myStrings属性也会影响原始列表中的等效对象。
因此两者之间没有立即差异。
回答您的问题,选项b是否会更改myStrings本身。
关于性能,是的。如本post所述:
是的,
IEnumerable<T>.ToList()
确实会对性能产生影响, 是 O(n)操作,尽管可能只需要关注 性能至关重要的操作。
ToList()
操作将使用[List(IEnumerable<T> collection)
] [2]构造函数。此构造函数必须复制 数组(通常为IEnumerable<T>
),否则为将来 原始数组的修改将在源T[]
上更改 也是通常不希望的。
这将回答您的第二个问题,即是否会影响性能。