安全&在C#中对显式接口成员的简单访问

时间:2010-05-20 18:02:57

标签: c# interface casting implicit-cast

当我在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我认为隐式转换比明确转换更好,因为稍后更改{{1}的声明在运行时将导致编译错误而不是MyType。但是,我有点喜欢显式转换语法的简单性,并且经常看到它在其他人的代码中使用。

我的问题有三个:

  • 您更喜欢上述哪个选项(以及为什么)?
  • 有更好的方法吗?
  • 有可能在隐式强制转换时执行显式强制转换有哪些最佳做法?

4 个答案:

答案 0 :(得分: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();
    }
}

答案 1 :(得分:1)

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

至于最后一个,如果你真的必须依赖于对一个实现(一个特定的派生类)的编程,那么在尝试对它做任何事情之前,确保该对象可以被强制转换。像这样:

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

答案 2 :(得分:0)

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

答案 3 :(得分:-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... */ }

     }
}