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

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

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 = (IMyInterface)someobj;

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

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

其他回答

这取决于,你想检查null后使用"as"或你更喜欢你的应用程序抛出一个异常?

我的经验法则是,如果我总是期望变量在我想要的时候是我期望的类型,我就使用强制转换。如果变量可能不会强制转换为我想要的,并且我准备从使用as处理空值,那么我将使用as。

看看这些链接:

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

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

请忽略Jon Skeet的建议,re:避免测试-强制转换模式,即:

if (randomObject is TargetType)
{
    TargetType foo = randomObject as TargetType;
    // Do something with foo
}

认为这比强制转换和空测试花费更多的想法是错误的:

TargetType convertedRandomObject = randomObject as TargetType;
if (convertedRandomObject != null)
{
    // Do stuff with convertedRandomObject
}

这是一种不起作用的微观优化。我运行了一些实际的测试,测试-强制转换实际上比强制转换-空比较更快,而且更安全,因为如果强制转换失败,则不可能在if之外的作用域中有空引用。

如果您想知道为什么测试-强制转换更快,或者至少不会更慢,有一个简单而复杂的原因。

简单:即使是简单的编译器也会将两个类似的操作(如test-and-cast)合并为一个测试和分支。强制转换-空测试可能强制执行两个测试和一个分支,一个用于类型测试和失败时转换为空,一个用于空检查本身。至少,它们都将优化为单个测试和分支,因此测试-强制转换既不会比强制转换-空测试慢也不会快。

复杂:为什么测试-强制转换更快:强制转换-空测试将另一个变量引入到外部作用域,编译器必须实时跟踪这个变量,并且它可能无法优化掉这个变量,这取决于你的控制流有多复杂。相反,“测试-强制转换”只在分隔的作用域内引入新变量,这样编译器就知道该变量在作用域退出后失效,从而更好地优化寄存器分配。

所以,请让这个“强制转换-空测试比测试-强制转换更好”的建议死掉吧。请。测试-强制转换既安全又快速。

如果不能强制转换,"as"将返回NULL。

之前的强制转换将引发异常。

对于性能而言,引发异常的代价通常更大。

两者之间一个更微妙的区别是,当涉及到强制转换操作符时,"as"关键字不能用于强制转换:

public class Foo
{
    public string Value;

    public static explicit operator string(Foo f)
    {
        return f.Value;
    }

}

public class Example
{
    public void Convert()
    {
        var f = new Foo();
        f.Value = "abc";

        string cast = (string)f;
        string tryCast = f as string;
    }
}

这将不会在最后一行进行编译(尽管我认为在以前的版本中是这样),因为“as”关键字不考虑强制转换操作符。line string cast = (string)f;不过效果还不错。