Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# foreach和泛型编译器问题_C#_.net_Generics_Compiler Construction_Foreach - Fatal编程技术网

C# foreach和泛型编译器问题

C# foreach和泛型编译器问题,c#,.net,generics,compiler-construction,foreach,C#,.net,Generics,Compiler Construction,Foreach,我使用了一个类似于以下内容的接口和类: public interface IIdentity { int Id { get; set; } } public class Identity : IIdentity { public int Id { get; set; } } var identities = new List<Wrapper<IIdentity>>(); identities.Add( new Wrapper<IIdentity&

我使用了一个类似于以下内容的接口和类:

public interface IIdentity
{
    int Id { get; set; }
}

public class Identity : IIdentity
{
    public int Id { get; set; }
}
var identities = new List<Wrapper<IIdentity>>();
identities.Add( new Wrapper<IIdentity> { WrappedObject = new Identity { Id = 1 }, Name = "John", Order = 1 } );
identities.Add( new Wrapper<IIdentity> { WrappedObject = new Identity { Id = 2 }, Name = "Jane", Order = 2 } );
identities.Add( new Wrapper<IIdentity> { WrappedObject = new Identity { Id = 3 }, Name = "Joe", Order = 3 } );
我正在创建
标识
类的实例,并将其添加到
列表
(稍后称为实例创建块)

最近,我需要添加更多关于
IIdentity
实例的数据,而不需要对
IIdentity
Identity
进行任何修改。因此,我添加了以下类:

public class Wrapper<T> where T : class
{
    public T WrappedObject { get; set; }
    public string Name { get; set; }
    public int Order { get; set; }
}
第2行:

foreach ( var identity in identities )

问题是为什么编译器在修改1或2未到位时成功编译了应用程序?

编译器看到
标识的类型是
列表
,并且可以看到
包装器
没有实现
IIdentity
。但是,这本身不足以产生编译时错误,因为可能有这样的派生类:

class DerivedWrapper<T> : Wrapper<T>, IIdentity { ... }
class-derivedwapper:Wrapper,IIdentity{…}
DerivedWrapper
的实例可以合法地放在
标识
中,因此编译器必须在运行时尝试将
identity
强制转换为
IIdentity
,如果失败,则引发异常

这两个修改以不同的方式对此产生影响:

  • 如果
    包装器
    密封的
    ,那么编译器知道不可能有这样的派生类,因此运行时强制转换永远不会成功;有益的是,它将此升级为编译时错误

  • 如果使用带有
    var
    的隐式类型,则编译器将
    var
    解析为
    identity
    的静态类型,在本例中为
    Wrapper
    。这意味着循环体试图访问不存在的成员
    Wrapper.Id
    成员,因此出现编译时错误


  • 史蒂文:这个问题不是被长镜头愚弄的。
    foreach ( IIdentity identity in identities )
    
    foreach ( var identity in identities )
    
    class DerivedWrapper<T> : Wrapper<T>, IIdentity { ... }