即使枚举类型被密封,foreach也不会打字检查

KFL*_*KFL 1 c# foreach typechecking

我对这个问题有类似的问题.而是我的SomeClass工具SomeInterface.在这种情况下,即使我标记SomeClasssealed,编译器时间类型检查仍然没有启动.例如下面.

问题1:为什么编译器不会出错,因为循环变量的类型与源枚举的元素类型不兼容?

编译器类型检查对我来说很重要,因为我正在重构一个大项目,将枚举源(source在a中foreach (SomeClass foo in source))更改IEnumerable<SomeClass>IEnumerable<SomeInterface>.有时我忘记将循环中的枚举器类型声明更改SomeClassSomeInterface,并且项目仍然编译.那会破坏事情真的很糟糕!!

问题2:您有什么建议让这种重构类型安全吗?

请注意,我无法将循环变量类型更改为隐式,var因为它正在退出代码库.但我能够更改接口的声明及其具体的实现类.

class Program
{
    static void Main(string[] args)
    {
        IEnumerable<SomeInterface> someFoos = new SomeInterface[] { new SomeOtherClass(), new SomeOtherClass(), new SomeOtherClass() };
        foreach (SomeClass foo in someFoos)
        {
            foo.ToString(); // runtime InvalidCastException
        }
    }
}

interface SomeInterface { }

sealed class SomeClass : SomeInterface
{
    public override string ToString()
    {
        return "SomeClass";
    }
}

class SomeOtherClass : SomeInterface
{
    public override string ToString()
    {
        return "SomeOtherClass";
    }
}
Run Code Online (Sandbox Code Playgroud)

Eri*_*ert 8

您在一个问题中提出了两个问题.几乎总是如此,你已经回答了你的两个问题之一.将来,考虑每个问题提出一个问题; 你更有可能回答你的问题.

我会回答你的第一个问题.

问题1:为什么编译器不会出错,因为循环变量的类型与源枚举的元素类型不兼容?

这是一个"为什么不"的问题,很难回答"为什么不"的问题; 他们预先假定世界应该是一种不同的方式,并问为什么不是.实际上,为什么世界不是你想要的那样,有无数的理由.我的建议是你不要再问"为什么不呢?" 问题在这里.相反,尝试询问有关世界的问题.

所以让我澄清这个问题.我们有

foreach(X item in collection)
Run Code Online (Sandbox Code Playgroud)

哪个collection是序列Y.

问题:X和之间的关系必须Y是什么?

Y必须明确可转换为X.也就是说,表单的强制转换操作符(X)必须合法才能应用于类型的项目Y.

这是少见的情况之一,其中C#将代表您自动插入强制转换操作,而代码中不会显示强制转换操作符.

问题:哪种语言设计原则表明这种情况应该是罕见的?

C#被设计为静态检查的类型安全语言; 此转换将类型检查移动到运行时而不是编译时,从而降低了安全性.

问题:语言设计决策需要在竞争原则之间进行权衡.导致C#设计团队在语言中包含"隐形"演员的令人信服的场景是什么?

foreach循环的语义是在将泛型添加到语言之前开发的.这意味着序列可能是IEnumerable,因此将是一系列objects.但是用户可能知道特定序列是所有字符串.因此,在C#1.0中,此代码非常常见:

foreach(object item in collection)
{
    string s = (string)item;
    ...
Run Code Online (Sandbox Code Playgroud)

这似乎是不必要的冗长.因此,语言设计团队决定允许转换为循环变量类型.

有人可能会合理地指出,这会增加您发现的错误的可能性.另一个特性可能是转换仅在转换时发生object.可能还有其他设计选择.C#设计团队选择明确转换,这就是我们必须接受的.

在反事实的世界中,从第一天开始就可以获得通用收藏品,设计可能会有所不同.但是那种反事实的推理并不是很有效率.