C# 不可枚举。强制转换(<;T>;复制对象?

C# 不可枚举。强制转换(<;T>;复制对象?,c#,casting,C#,Casting,我有一个对象层次结构 public class MyBase {} public class MyDerived : MyBase {} 而且 List<MyBase> myList; 我在上阅读了MSDN文档,但我不清楚Cast和ToList操作是在内存中创建对象的新副本,还是简单地允许编译器访问现有对象,就好像它们是列表一样 毫不奇怪(!)它投射了它们 我阅读了Enumerable.Cast上的MSDN文档,但我不清楚Cast和ToList操作是在内存中创建对象的新副本,还是

我有一个对象层次结构

public class MyBase {}
public class MyDerived : MyBase {}
而且

List<MyBase> myList;
我在上阅读了MSDN文档,但我不清楚
Cast
ToList
操作是在内存中创建对象的新副本,还是简单地允许编译器访问现有对象,就好像它们是
列表一样

毫不奇怪(!)它
投射了它们

我阅读了Enumerable.Cast上的MSDN文档,但我不清楚Cast和ToList操作是在内存中创建对象的新副本,还是仅仅允许编译器像访问列表一样访问现有对象


是的,具体地说,此场景将允许编译器访问现有对象,就像其名称所示,
Cast()
仅强制转换对象一样:

public static IEnumerable<TResult> Cast<TResult>(this IEnumerable source) { 
    IEnumerable<TResult> typedSource = source as IEnumerable<TResult>;
    if (typedSource != null) return typedSource; 
    if (source == null) throw Error.ArgumentNull("source");
    return CastIterator<TResult>(source);
}

static IEnumerable<TResult> CastIterator<TResult>(IEnumerable source) {
    foreach (object obj in source) yield return (TResult)obj; 
} 
公共静态IEnumerable强制转换(此IEnumerable源代码){
IEnumerable typedSource=源为IEnumerable;
如果(typedSource!=null)返回typedSource;
if(source==null)抛出错误.ArgumentNull(“source”);
返回迭代器(源);
}
静态IEnumerable CastIterator(IEnumerable源){
foreach(源中的对象obj)收益率返回(TResult)obj;
} 
在.Net中,根本不可能复制任意对象。
Cast()
复制东西是没有意义的

注意,如果
T
是值类型,
Cast()
将复制结构;值类型总是被复制的。(作为
ref
参数传递时除外)

强制转换调用:

enumerable.Cast<T>();
以及:

enumerable.ToList()
相当于:

enumerable.Select(x=>(T)x)
List<T> myList = new List<T>();
foreach(T item in enumerable)
{
   myList.Add(item);
}
List<T2> myList = new List<T2>();
foreach(T item in enumerable)
{
   myList.Add((T2)item);
}
List myList=new List();
foreach(可枚举中的T项)
{
myList.Add(项目);
}
所以

enumerable.Cast.ToList()
相当于:

enumerable.Select(x=>(T)x)
List<T> myList = new List<T>();
foreach(T item in enumerable)
{
   myList.Add(item);
}
List<T2> myList = new List<T2>();
foreach(T item in enumerable)
{
   myList.Add((T2)item);
}
List myList=new List();
foreach(可枚举中的T项)
{
myList.Add((T2)项);
}
如果enumerable包含任何不属于T2可强制转换类型的条目,这两个条目都将立即爆炸

那样会更安全

  enumerable.Where(x=>x is T2).Cast<T2>().ToList();
enumerable.Where(x=>x是T2.Cast().ToList();

enumerable.OfType().ToList();

但是,这些都不会复制原始集合中包含的对象。它们只是创建包含对原始对象引用的集合。

实际上不可能复制任意托管对象。用户定义的转换纯粹是编译时功能;没有运行时方法使用它们。@SLaks:再次感谢。我今天学到了一些东西。你帮我省去了尝试的时间:)使用ToList()会创建副本,还是不会?@sos00:错。复制一个对象是不可能的
ToList()
复制列表,但它仍然引用相同的对象。在此处提及您自己的注释的相反内容可能会很有用:如果您在包含操作类型的程序集中实现与此完全相同的代码,则其行为可能与标准扩展不同:
(TResult)obj
可以调用用户定义的转换运算符(例如,
类X{public static implicit operator Y(){…}
)@sehe:仍然错误。泛型是在运行时完成的;对泛型类型的转换或从泛型类型转换将永远不会调用用户定义的运算符。叹气。我在哪里可以找到这些信息?顺便说一下,这也意味着对非泛型类型的转换仍然可以调用用户定义的转换?例如,
List xs;var convertedtoYs=xs.cast()
?您知道,X没有通用性,也没有为新列表分配YSo内存?是的。内存是为列表数据结构分配的。注意:我使用OfType扩展方法添加了另一种替代方法,该方法过滤并强制转换到定义的类型。(enumerable.OfType().ToList())将仅返回那些可转换为T2类型的元素的列表。
  enumerable.OfType<T2>().ToList();