0

当我在 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将导致编译错误而不是运行时错误。但是,我更喜欢显式强制转换语法的简单性,并且经常看到它在其他人的代码中使用。IMyTypeMyTypeInvalidCastException

我的问题有三个:

  • 您更喜欢上述哪个选项(以及为什么)?
  • 有一个更好的方法吗?
  • 当可以进行隐式转换时,关于执行显式转换的最佳实践是什么?
4

4 回答 4

2

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

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();
    }
}
于 2010-05-20T19:57:44.093 回答
1

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

至于最后一个,如果您真的必须依赖于针对实现(特定派生类)进行编程,那么请确保在尝试对其进行任何操作之前可以将对象转换为类型。像这样的东西:

var IMyType item3 = item as MyConcreteType;
if(item3 != null) {
    item3.SayHello();
}
于 2010-05-20T18:09:32.340 回答
0

如果您不确定该对象是否是接口的实例,请执行 as/null 检查。通常你从方法/函数调用返回一个接口,在这种情况下你只需将它存储在一个没有强制转换的变量中(尽管可能仍然需要空检查)。

于 2010-05-20T19:52:59.420 回答
-1

我通常喜欢它:

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... */ }

     }
}
于 2010-05-20T18:12:16.253 回答