安全且简单地访问C#中的显式接口成员
-
03-10-2019 - |
题
当我在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... */ }
}
}
不隶属于 StackOverflow