当我在C#中使用显式接口实现时,通常有必要将对象施加到其一个接口之一,以访问该接口的成员。由于编译时间类型检查提供的可靠性和可维护性的提高,我一直更喜欢使用隐式转换来执行此操作。我知道这样做的唯一方法涉及两行代码,并将另一个变量引入范围。以下是一个示例:

public interface IMyType
{
    string SayHello();
}

public class MyType : IMyType
{
    string IMyType.SayHello() { return "Hello!"; }
}

class Program
{
    static void Main(string[] args)
    {
        var item = new MyType();

        // Option 1 - Implicit cast. Compile time checked but takes two lines.
        IMyType item2 = item;
        System.Console.WriteLine(item2.SayHello());

        // Option 2 - One line but risks an InvalidCastException at runtime if MyType changes.
        System.Console.WriteLine(((IMyType)item).SayHello());

        // Option 3 - One line but risks a NullReferenceException at runtime if MyType changes.
        System.Console.WriteLine((item as IMyType).SayHello());
    }
}

因为编译器 知道MyType 工具 IMyType 我认为隐性演员比明确的演员更好,因为以后更改了声明 MyType 将导致编译错误,而不是 InvalidCastException 在运行时。但是,我在某种程度上更喜欢明确的铸造语法的简单性,并且经常看到它在其他人的代码中使用。

我的问题是三倍:

  • 您更喜欢上述哪些选项(以及为什么)?
  • 有一个更好的方法吗?
  • 如果可能的隐性演员,那么在表演明确的演员表中有哪些最佳实践?
有帮助吗?

解决方案

这是一个编译时间检查一个衬里:

public static class Converter
{
    public static T ReturnAs<T>(T item)
    {
        return item;
    }
}


class Program
{
    static void Main(string[] args)
    {
        var item = new MyType();

        // Option 1 - Implicit cast. Compile time checked but takes two lines.
        IMyType item2 = item;
        System.Console.WriteLine(item2.SayHello());

        // Option 2 - One line but risks an InvalidCastException at runtime if MyType changes.
        System.Console.WriteLine(((IMyType)item).SayHello());

        // Option 3 - One line but risks a NullReferenceException at runtime if MyType changes.
        System.Console.WriteLine((item as IMyType).SayHello());

        // Option 4 - compile time one liner
        Converter.ReturnAs<IMyType>(item).SayHello();
    }
}

其他提示

作为所有三个问题的答案:依靠隐式演员作为一般规则。您正在针对接口进行编程,而不是实现。

至于最后一个,如果您确实必须依靠针对实现的编程(特定的派生类),请确保可以在尝试对其进行任何操作之前将对象施放为类型。这样的事情:

var IMyType item3 = item as MyConcreteType;
if(item3 != null) {
    item3.SayHello();
}

如果您不确定该对象是接口的实例,则进行AS/NULL检查。通常,您会从方法/函数调用中返回接口,在这种情况下,您只需将其存储在没有铸件的情况下(尽管仍然需要零检查)。

我通常喜欢:

class Program
{
    static void Main(string[] args)
    {
        var item = new MyType();
        if( item is IMyType ){
          Console.WriteLine( (item as IMyType).SayHello() );
        }
        else { /* Do something here... */ }

     }
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top