在编程接口时,我发现我做了很多强制转换或对象类型转换。

这两种转换方法有什么区别吗?如果是的话,是否有成本差异,或者这对我的程序有什么影响?

public interface IMyInterface
{
    void AMethod();
}

public class MyClass : IMyInterface
{
    public void AMethod()
    {
       //Do work
    }

    // Other helper methods....
}

public class Implementation
{
    IMyInterface _MyObj;
    MyClass _myCls1;
    MyClass _myCls2;

    public Implementation()
    {
        _MyObj = new MyClass();

        // What is the difference here:
        _myCls1 = (MyClass)_MyObj;
        _myCls2 = (_MyObj as MyClass);
    }
}

另外,“一般来说”首选的方法是什么?


当前回答

这不是对问题的回答,而是对问题代码示例的注释:

通常你不需要强制转换一个对象,例如IMyInterface到MyClass。接口的伟大之处在于,如果你把一个对象作为实现接口的输入,那么你就不需要关心你得到的是什么类型的对象。

如果你将IMyInterface转换为MyClass,那么你已经假设你得到了一个MyClass类型的对象,使用IMyInterface是没有意义的,因为如果你用其他实现IMyInterface的类来填充你的代码,它会破坏你的代码……

现在,我的建议是:如果你的接口设计得很好,你可以避免大量的类型转换。

其他回答

看看这些链接:

http://gen5.info/q/2008/06/13/prefix-casting-versus-as-casting-in-c/ http://www.codeproject.com/Articles/8052/Type-casting-impact-over-execution-performance-in

它们向您展示了一些细节和性能测试。

你的选择很大程度上取决于你需要什么。 我更喜欢显式类型转换

IMyInterface = (IMyInterface)someobj;

因为如果对象应该由IMyInterface类型,而它不是-这肯定是问题。 最好尽早得到错误,因为准确的错误将被修复,而不是修复它的副作用。

但是如果你处理的方法接受object作为参数,那么你需要在执行任何代码之前检查它的确切类型。在这种情况下,可以避免InvalidCastException。

as关键字的工作原理与兼容引用类型之间的显式强制转换相同,主要区别在于转换失败时它不会引发异常。相反,它在目标变量中产生一个空值。由于异常在性能方面非常昂贵,因此它被认为是一种更好的强制转换方法。

除了这里已经暴露的所有内容,我刚刚发现了一个我认为值得注意的实际差异,在显式选角之间

var x = (T) ...

相对于使用as操作符。

下面是例子:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(GenericCaster<string>(12345));
        Console.WriteLine(GenericCaster<object>(new { a = 100, b = "string" }) ?? "null");
        Console.WriteLine(GenericCaster<double>(20.4));

        //prints:
        //12345
        //null
        //20.4

        Console.WriteLine(GenericCaster2<string>(12345));
        Console.WriteLine(GenericCaster2<object>(new { a = 100, b = "string" }) ?? "null");

        //will not compile -> 20.4 does not comply due to the type constraint "T : class"
        //Console.WriteLine(GenericCaster2<double>(20.4));
    }

    static T GenericCaster<T>(object value, T defaultValue = default(T))
    {
        T castedValue;
        try
        {
            castedValue = (T) Convert.ChangeType(value, typeof(T));
        }
        catch (Exception)
        {
            castedValue = defaultValue;
        }

        return castedValue;
    }

    static T GenericCaster2<T>(object value, T defaultValue = default(T)) where T : class
    {
        T castedValue;
        try
        {
            castedValue = Convert.ChangeType(value, typeof(T)) as T;
        }
        catch (Exception)
        {
            castedValue = defaultValue;
        }

        return castedValue;
    }
}

底线:GenericCaster2不能用于结构类型。GenericCaster意志。

如果转换失败,'as'关键字不会抛出异常;它将变量设置为null(或为值类型的默认值)。