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

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

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);
    }
}

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


当前回答

这并不能回答你的问题,但我认为这是一个重要的相关点。

如果你正在为一个接口编程,你不应该需要强制转换。希望这种类型的演员很少。如果不是,您可能需要重新考虑一些接口。

其他回答

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

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

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

如果您使用针对。net Framework 4的Office PIAs。X你应该使用as关键字,否则它将无法编译。

Microsoft.Office.Interop.Outlook.Application o = new Microsoft.Office.Interop.Outlook.Application();
Microsoft.Office.Interop.Outlook.MailItem m = o.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olMailItem) as Microsoft.Office.Interop.Outlook.MailItem;

当目标是。net 2.0时,强制转换是可以的:

Microsoft.Office.Interop.Outlook.MailItem m = (Microsoft.Office.Interop.Outlook.MailItem)o.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olMailItem);

当目标是。net 4时。X的误差为:

缺少编译器需要的成员'Microsoft.CSharp.RuntimeBinder.Binder.Convert'

缺少编译器需要的成员'Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create'

如果转换失败,'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;不过效果还不错。

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

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意志。