代码之家  ›  专栏  ›  技术社区  ›  Joseph Sturtevant

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

  •  0
  • Joseph Sturtevant  · 技术社区  · 14 年前

    当我在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 在运行时。然而,我有点喜欢显式转换语法的简单性,并且经常在其他人的代码中看到它的使用。

    我的问题有三个方面:

    • 你更喜欢上述哪种选择(为什么)?
    • 有更好的方法吗?
    • 在可能进行隐式强制转换时,执行显式强制转换的最佳实践是什么?
    4 回复  |  直到 14 年前
        1
  •  2
  •   Marius    14 年前

    下面是一个编译时检查的一行程序:

    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();
        }
    }
    
        2
  •  1
  •   Agent_9191    14 年前

    作为对这三个问题的回答:一般情况下依赖隐式投射。您是根据接口而不是实现进行编程的。

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

    var IMyType item3 = item as MyConcreteType;
    if(item3 != null) {
        item3.SayHello();
    }
    
        3
  •  0
  •   Rodrick Chapman    14 年前

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

        4
  •  -1
  •   Sunny    14 年前

    我通常喜欢这样:

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