为什么转换为接口不是在C#中检查编译时间? [英] Why cast to interface is not compile time checked in C# ?

查看:68
本文介绍了为什么转换为接口不是在C#中检查编译时间?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述





我刚刚看到一个人提出的一个问题,其中没有人提出了一个令人满意的答案,只是出于好奇我也想要要知道为什么编译时间合法,但是当然它会在运行时失败,这里是代码:



Hi,

I just saw a question asked by someone on a different to which no one has porivded a staisfacotry answer, and just out of curiousity i also wanted to know why is it compile time legal, but ofcourse it would fail at run-time, here is the code:

public class DummyClassFactory
    {
        public Object GetDummyClassInstance()
        { 
            var dummyClass = new DummyClass();
			
            switch (DateTime.Now.DayOfWeek)
            {
                // Starting on monday.
                case DayOfWeek.Monday:
                    return (IDisposable)dummyClass;
                
               
                case DayOfWeek.Thursday:
                    return (IServiceProvider)dummyClass;
                case DayOfWeek.Friday:
                    return (IEquatable<List<Single>>)dummyClass;
                case DayOfWeek.Saturday:
                    return (IFormattable)dummyClass;
                
            }
            // return (DummyClassFactory)dummyClass; 
            return dummyClass;
        }
    }

    public class DummyClass { }
    public interface IDummyClass { }





有人可以说清楚,为什么会这样?



这是演示小提琴:.NET DEMO小提琴 [ ^ ]



谢谢,

Ehsan Sajjad



我尝试过:





Can someone please shed some light, why is it so?

Here is the demo fiddle : .NET DEMO Fiddle[^]

Thanks,
Ehsan Sajjad

What I have tried:

public class DummyClassFactory
    {
        public Object GetDummyClassInstance()
        { 
            var dummyClass = new DummyClass();
			
            switch (DateTime.Now.DayOfWeek)
            {
                // Starting on monday.
                case DayOfWeek.Monday:
                    return (IDisposable)dummyClass;
                
               
                case DayOfWeek.Thursday:
                    return (IServiceProvider)dummyClass;
                case DayOfWeek.Friday:
                    return (IEquatable<List<Single>>)dummyClass;
                case DayOfWeek.Saturday:
                    return (IFormattable)dummyClass;
                
            }
            // return (DummyClassFactory)dummyClass; 
            return dummyClass;
        }
    }

    public class DummyClass { }
    public interface IDummyClass { }

推荐答案

这有点复杂,但我会尝试解释......



请记住,一个班级可以来自单个基类(具体或抽象),但也可以继承多个接口。所以后代类可以实现原始基类没有的接口。

It's a bit complicated, but I'll try to explain...

Remember that a class can derive from a single base class (concrete or abstract), but can also inherit multiple interfaces. So descendant classes can implement interfaces that the original base class did not.
class MyBase{}
class MyDerived : MyBase {}
class MyOtherDerived : MyDerived, IInterface1, IInterface2 {}



由于MyBase类型的变量可以包含基于MyBase的任何类型的对象,因此可以想象它包含一个MyOtherDerived类实例 - 它支持两个接口,因此它可以被转换要么(通过适当的运行时检查以确保它有效)。

这很简单,你可以说没有派生类实现IDontKnowWhatToCallIt,所以你不应该强制转换它并且你应该得到编译器错误。



但是......系统不知道这一点。完全可能的是,一个不同的程序集完全创建了一个派生自MyBase的类,并且实现了IDontKnowWhatToCallIt接口 - 因此它不会在不严重破坏代码的情况下创建编译时错误!



如果您的基类是密封它可以检查 - 它确实存在,并且会引发编译器错误。但是对于可派生类,它必须在安全方面犯错并让强制转换并依赖运行时检查来抛出异常。


Since a variable of type MyBase could contain any type of object based on MyBase, it could conceivably contain a MyOtherDerived class instance - which supports two interfaces, so it can be cast to either (with the appropriate runtime checks to make sure it works).
That's all simple enough, and you could say "No derived class implements IDontKnowWhatToCallIt, so you shouldn't be able to cast to it and you should get a compiler error".

But ... the system doesn't know that. It's entirely possible that a different assembly altogether does create a class derived from MyBase and that does implement the IDontKnowWhatToCallIt Interface - so it can't create a compile time error without seriously mucking up your code!

If your base class is sealed it can check - and it does, and will raise a compiler error. But for derivable classes, it has to err on the "safe" side and let the cast through and rely on the run time checks to throw an exception.


据我了解情况而定,您的类可以扩展为支持代码中提到的接口,例如通过继承。所以编译器不确定演员是否总是会失败。



如果你封印课程,情况会发生巨大变化:

As far as I understand the situation, your class can be extended to support the mentioned interfaces in the code for example by inheritance. So the compiler is not sure if the cast would always fail.

Things change dramatically if you seal the class:
public sealed class DummyClass { }


这篇关于为什么转换为接口不是在C#中检查编译时间?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆