C#中,隐式转换(implicit)和显式转换(explicit)重载方法,不支持将接口类型作为转换的源类型或目标类型

我们知道可以在C#的类和结构体中,定义隐式转换(implicit)和显式转换(explicit)的重载方法,也称作"用户定义的转换(User-defined conversions)"。但是其实在C#中有一个规定,就是不能将接口类型作为隐式转换和显式转换重载方法的源或目标类型。

新建一个.NET Core控制台项目。

我们在项目中定义了一个泛型类Container<T>,我们在其中定义了它的隐式转换重载方法,如下所示:

using System;

namespace NetCoreConversionDemo
{
    public interface IHelper
    {

    }

    public class Helper : IHelper
    {

    }

    public class Container<T>
    {
        //定义隐式转换重载方法
        public static implicit operator Container<T>(T source)
        {
            Console.WriteLine("Implicit conversion called");
            return new Container<T>();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Container<IHelper> container = new Container<IHelper>();
            Helper helper = new Helper();

            container = helper;//输出Implicit conversion called

            IHelper iHelper = new Helper();

            //container = iHelper;//编译错误:CS0266    Cannot implicitly convert type 'NetCoreConversionDemo.IHelper' to 'NetCoreConversionDemo.Container<NetCoreConversionDemo.IHelper>'.

            Console.WriteLine("Press any key to end...");
            Console.ReadKey();
        }
    }
}

我们如果在上面代码中取消注释//container = iHelper;,那么这一行在代码编译时会报错,提示不能将接口类型IHelper转换为泛型类Container<IHelper>

同样,如果我们给泛型类Container<T>定义一个显式转换重载方法,如下所示:

using System;

namespace NetCoreConversionDemo
{
    public interface IHelper
    {

    }

    public class Helper : IHelper
    {

    }

    public class Container<T>
    {
        //定义显式转换重载方法
        public static explicit operator Container<T>(T source)
        {
            Console.WriteLine("Explicit conversion called");
            return new Container<T>();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Container<IHelper> container = new Container<IHelper>();
            Helper helper = new Helper();

            container = (Container<IHelper>)helper;//输出Explicit conversion called

            IHelper iHelper = new Helper();

            container = (Container<IHelper>)iHelper;//抛出System.InvalidCastException异常:Unable to cast object of type 'NetCoreConversionDemo.Helper' to type 'NetCoreConversionDemo.Container`1[NetCoreConversionDemo.IHelper]'.

            Console.WriteLine("Press any key to end...");
            Console.ReadKey();
        }
    }
}

虽然上面代码可以编译成功,但是当执行代码时,会在container = (Container<IHelper>)iHelper;抛出System.InvalidCastException异常,同样这是因为我们正在将接口类型IHelper通过显式转换重载方法,转换为泛型类Container<IHelper>,这是不允许的。

下面这篇帖子也解释了,为什么在使用隐式转换和显式转换重载方法时,不能将接口类型作为转换的源或目标类型:

implicit operator using interfaces

下面这篇微软的官方文档,也提到了接口类型不能作为"用户定义的转换(User-defined conversions)"的源或目标类型:

User-defined conversions

其中有提到:

  • ...
  • Neither S0 nor T0 is an interface_type.
  • ...

下面这篇微软的官方文档,解释了为什么不能将接口类型作为"用户定义的转换(User-defined conversions)"的源或目标类型:

Conversion operators

其中有提到:

User-defined conversions are not allowed to convert from or to interface_types. In particular, this restriction ensures that no user-defined transformations occur when converting to an interface_type, and that a conversion to an interface_type succeeds only if the object being converted actually implements the specified interface_type.

所以当我们在类和结构体中,定义隐式转换和显式转换重载方法后,一定要明白,这些"用户定义的转换(User-defined conversions)"方法是不能直接用于接口类型的。

参考文献:

implicit operator using interfaces

Conversions

Classes