我想知道在下面的代码中使用关键字“as”是否是一种安全的方式(即不会爆炸)在C#中进行投射:
public void abc(ref Object dataSource)
{
DataTable table = dataSource as DataTable;
}
有更安全的投射方式吗?
答案 0 :(得分:40)
它不会爆炸......但这并不一定意味着它是安全的。
通常当我使用强制转换进行引用转换时,这是因为我确实认为执行时类型是我指定的类型。如果不是,则表示我的代码中存在错误 - 我宁愿将其表现为异常。
如果您的系统中存在错误数据,那么继续好像一切正常就是危险路径,而不是安全路径。这就是as
将你带走的方式,而演员会抛出一个InvalidCastException
,在你有机会对坏数据造成混乱之前中止你所做的一切。
as
是好的 - 如果它不表示错误。您几乎总是看到以下模式:
Foo x = y as Foo;
if (x != null)
{
...
}
有关as
的详细信息,请参阅MSDN。
另请注意,可能不希望在您的方法中使用ref
。有关详细信息,请参阅我的article on parameter passing。大多数时候,如果我看到人们经常使用ref
,那是因为他们不明白它的真正含义:)
答案 1 :(得分:12)
这取决于你所说的“安全”。问问自己哪个更安全:带断路器的设备,还是没有断路器的设备?没有保险丝的人更有可能洗完衣服,但也更容易烧毁你的房子。
您可能知道,在C#中进行显式转换有两种主要方法:
foo = (MyType)myObject; //Cast myObject to MyType or throw an error
foo = myObject as MyType; //Cast myObject to MyType or set foo to null
不同之处在于,如果运行时不知道如何将myObject
强制转换为MyType
,则第一行将抛出异常,而第二行仅将foo
设置为{ {1}}。如果生成在null
中的对象不是myObject
,或者MyType
没有明确转换为MyType
,则会发生这种情况。
哪一个更安全?好吧,如果“安全”意味着“如果演员表无效则不会抛出异常”,那么myObject
表单会更安全。如果投射失败,as
会立即爆炸,但如果您尝试对(MyType)myObject
执行某些操作myObject as MyType
,则foo
只会爆炸({1}}例如调用null
)。
另一方面,有时会抛出异常是最安全的事情。如果您的代码中有错误,您可能想立即知道。如果始终期望foo.ToString()
为myObject
,那么失败的演员表示某处存在错误。如果你继续进行铸造工作,那么你的程序会突然处理垃圾数据!它可能会进一步爆炸,使调试变得困难,或者 - 更糟糕 - 它可能永远不会爆炸,只是静静地做你没想到的事情。这可能会造成各种各样的破坏。
因此,这两种形式都不是本质上安全或正确的,它们只适用于不同的事物。如果出现以下情况,您可以使用MyType
表单:
myObject as MyType
是什么类型myObject
执行某些操作,但前提是myObject
类型MyType
可能不是myObject
,而且并不意味着存在错误一个例子是当你有一组不同的WebForm控件时,你想要清除它们中的所有TextBox:
MyType
通过这种方式,您的TextBox会被清除,其他所有内容都会被遗漏。
答案 2 :(得分:5)
DataTable table = dataSource as DataTable;
如果演员表不成功,使用as
将返回null
,因此不会爆炸。 - 这意味着您必须处理代码其余部分中table
为null
的情况。
答案 3 :(得分:4)
as
不会爆炸,但如果转换失败,变量将设置为null。你需要检查那个案例。
DataTable table = dataSource as DataTable;
if (table == null)
{
// handle case here.
}
答案 4 :(得分:2)
如果演员表无效,'as'运算符不会抛出异常。它只返回null。 ()方法将抛出异常。所以回答你的问题,这是最安全的方式。
这基本上是你需要的方式:
if( x is MyType )
{
MyType y = (MyType) x;
}
或
MyType y = x as MyType;
if( y != null )
{
// Do stuff
}
答案 5 :(得分:2)
这是一种安全的方式来投射它不会导致异常的事实。但是,如果您不小心,它可能会导致隐藏的错误。
使用as
时,如果强制转换失败,则生成的变量为null
。如果你没有检查这个,那么当你试图访问变量时你将会得到一个NullReferenceException
,并且它不清楚它为什么会失败(例如它是null
,因为转换失败或者做了别的事后来导致它为空)
答案 6 :(得分:2)
如果这是“安全”的意思,它不会抛出异常。但是,如果强制转换失败,table
将为空。
DataTable table = dataSource as DataTable;
如果转换失败,则不会抛出异常。将改为null。
DataTable table = (DataTable)dataSource;
如果演员表失败,将抛出异常。
在这方面是安全的,但是如果转换可能失败,那么添加一个空检查来处理它。
答案 7 :(得分:1)
取决于您要做的事情:
DataTable table = dataSource as DataTable;
if (table != null) ...
表示“dataSource
可能是DataTable
,我将检查它不是null
。”
DataTable table = (DataTable) dataSource;
表示“dataSource
肯定是是DataTable
,如果不是”{<1>}则会出现严重错误。
答案 8 :(得分:0)
如果dataSource可以作为DataTable转换,它将完成工作,这是安全的。但如果您担心它没有成功投射,您可以先检查dataSource.GetType()是否等于您尝试将其投射到的类型。
答案 9 :(得分:0)
如果使用as,则不会有运行时InvalidCastException,但表可能为null,因此您需要检查它。
答案 10 :(得分:0)
使用as
和普通强制转换之间的区别在于,如果无法执行强制转换(因为对象不是正确的类型),as
运算符将返回{{1 }}。正常演员会抛出异常。
所以他们都“安全” - 当演员阵容无法成功时,他们只会有不同的行为。