在编程接口时,我发现我做了很多强制转换或对象类型转换。
这两种转换方法有什么区别吗?如果是的话,是否有成本差异,或者这对我的程序有什么影响?
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);
}
}
另外,“一般来说”首选的方法是什么?
OP的问题仅限于特定的选角情况。标题涵盖了更多的情况。
以下是我目前能想到的所有相关选角情况的概述:
private class CBase
{
}
private class CInherited : CBase
{
}
private enum EnumTest
{
zero,
one,
two
}
private static void Main (string[] args)
{
//########## classes ##########
// object creation, implicit cast to object
object oBase = new CBase ();
object oInherited = new CInherited ();
CBase oBase2 = null;
CInherited oInherited2 = null;
bool bCanCast = false;
// explicit cast using "()"
oBase2 = (CBase)oBase; // works
oBase2 = (CBase)oInherited; // works
//oInherited2 = (CInherited)oBase; System.InvalidCastException
oInherited2 = (CInherited)oInherited; // works
// explicit cast using "as"
oBase2 = oBase as CBase;
oBase2 = oInherited as CBase;
oInherited2 = oBase as CInherited; // returns null, equals C++/CLI "dynamic_cast"
oInherited2 = oInherited as CInherited;
// testing with Type.IsAssignableFrom(), results (of course) equal the results of the cast operations
bCanCast = typeof (CBase).IsAssignableFrom (oBase.GetType ()); // true
bCanCast = typeof (CBase).IsAssignableFrom (oInherited.GetType ()); // true
bCanCast = typeof (CInherited).IsAssignableFrom (oBase.GetType ()); // false
bCanCast = typeof (CInherited).IsAssignableFrom (oInherited.GetType ()); // true
//########## value types ##########
int iValue = 2;
double dValue = 1.1;
EnumTest enValue = EnumTest.two;
// implicit cast, explicit cast using "()"
int iValue2 = iValue; // no cast
double dValue2 = iValue; // implicit conversion
EnumTest enValue2 = (EnumTest)iValue; // conversion by explicit cast. underlying type of EnumTest is int, but explicit cast needed (error CS0266: Cannot implicitly convert type 'int' to 'test01.Program.EnumTest')
iValue2 = (int)dValue; // conversion by explicit cast. implicit cast not possible (error CS0266: Cannot implicitly convert type 'double' to 'int')
dValue2 = dValue;
enValue2 = (EnumTest)dValue; // underlying type is int, so "1.1" beomces "1" and then "one"
iValue2 = (int)enValue;
dValue2 = (double)enValue;
enValue2 = enValue; // no cast
// explicit cast using "as"
// iValue2 = iValue as int; error CS0077: The as operator must be used with a reference type or nullable type
}
除了这里已经暴露的所有内容,我刚刚发现了一个我认为值得注意的实际差异,在显式选角之间
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意志。