在C#中使用"as"是一种安全的铸造方式吗?

dev*_*per 24 c# casting

我想知道在下面的代码中使用关键字"as"是否是一种安全的方式(即不会爆炸)在C#中进行转换:

public void abc(ref Object dataSource)
{
    DataTable table = dataSource as DataTable;
}
Run Code Online (Sandbox Code Playgroud)

有更安全的铸造方式吗?

Jon*_*eet 42

它不会爆炸......但这并不一定意味着它是安全的.

通常当我使用强制转换进行引用转换时,这是因为我真的认为执行时类型是我指定的类型.如果不是,则表示我的代码中存在错误 - 我宁愿将其表现为异常.

如果您的系统中存在不良数据,那么继续好像一切都很好是危险的路径,而不是安全路径.这就是as采取你的方式,而演员会抛出一个InvalidCastException,在你有机会用糟糕的数据造成混乱之前中止你所做的一切.

as如果它对于不属于给定类型的对象有效 - 如果它不表示错误则是好的.你几乎总能看到以下模式:

Foo x = y as Foo;
if (x != null)
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅MSDNas.

另请注意,您可能不希望ref在方法中使用.有关详细信息,请参阅有关参数传递的文章.大部分时间,如果我看到人们使用ref了很多,那是因为他们不明白它的真正含义:)

  • @developer:基本上阅读我链接的文章."参考"和"通过参考传递参数"之间存在很大差异.*不要用C++来思考 - 当你编写C#时,它会让你感到困惑. (3认同)

Jus*_*gan 13

这取决于你所说的"安全".问问自己哪个更安全:带断路器的设备,还是没有断路器的设备?没有保险丝的人更有可能完成洗衣服,但也更容易烧毁你的房子.

您可能知道,在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
Run Code Online (Sandbox Code Playgroud)

不同之处在于,如果运行时不知道如何转换myObjectMyType,则第一行将抛出异常,而第二行将仅设置foonull.如果居住的对象myObject不是a MyType,或者没有任何明确的强制转换MyType,就会发生这种情况myObject.

哪一个更安全?好吧,如果"安全"意味着"如果演员表无效则不会抛出异常",那么as表格更安全.如果施法失败,(MyType)myObject会立即爆炸,但myObject as MyType只有当你试图做一些foo你不能做的事情时才会爆炸null(比如打电话foo.ToString()).

另一方面,有时抛出异常是最安全的事情.如果您的代码中有错误,您可能想立即知道.如果myObject总是期望是a MyType,那么失败的演员意味着某处有一个错误.如果你继续进行铸造工作,那么你的程序会突然处理垃圾数据!它可能会进一步爆炸,使调试变得困难,或者 - 更糟糕 - 它可能永远不会爆炸,只是静静地做你没想到的事情.这可能会造成各种各样的破坏.

因此,这两种形式都不具有内在的安全性或正确性,它们只适用于不同的事物.您可以使用以下myObject as MyType表格:

  1. 你不肯定知道是什么类型myObject
  2. 你想做点什么myObject,但只有它是类型的MyType
  3. myObject可能是其他东西MyType,并不意味着有一个错误

一个例子是当你有一组不同的WebForm控件时,你想要清除它们中的所有TextBox:

foreach (var control in controls)
{
    var textbox = control as TextBox;
    if (textbox != null)
    {
        //Now we know it's a TextBox, so we know it has a Text property
        textbox.Text = string.Empty;
    }
}
Run Code Online (Sandbox Code Playgroud)

这样,您的TextBox就会被清除掉,其他一切都会被遗忘.


Bro*_*ass 5

DataTable table = dataSource as DataTable;
Run Code Online (Sandbox Code Playgroud)

如果演员阵容不成功,as则返回使用null,因此不会爆炸.-这意味着你将不得不处理的情况下,tablenull在你的代码的其余部分,虽然.