正在使用“;作为“;在C#中是一种安全的铸造方式

本文关键字:安全 一种 方式 作为 | 更新日期: 2023-09-27 17:59:20

我想知道在以下代码中使用关键字"as"是否是在C#中进行铸造的安全方法(即不会爆炸):

public void abc(ref Object dataSource)
{
    DataTable table = dataSource as DataTable;
}

有更安全的铸造方法吗?

正在使用“;作为“;在C#中是一种安全的铸造方式

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

通常,当我使用强制转换进行引用转换时,这是因为我非常非常认为执行时间类型就是我指定的类型。如果不是,那就表明我的代码中有一个错误——我宁愿它表现为一个例外。

如果你的系统中有坏数据,那么继续一切正常是危险的路径,而不是安全的

如果as对于对象不是给定类型的有效,则它是好的——如果它不指示错误。你几乎总是看到的模式:

Foo x = y as Foo;
if (x != null)
{
    ...
}

有关as功能的更多详细信息,请参阅MSDN。

还需要注意的是,可能不希望在方法中使用ref。有关更多详细信息,请参阅我关于参数传递的文章。大多数时候,如果我看到人们经常使用ref,那是因为他们不明白它的真正含义:)

这取决于你所说的"安全"是什么意思问问自己哪个更安全:带断路器的电器还是没有断路器的?没有保险丝的更有可能洗完你的衣服,但也更有可能烧毁你的房子。

正如您可能知道的,在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设置为as0。如果生活在myObject中的对象不是MyType,或者无论myObject是什么,都没有显式转换到MyType,就会发生这种情况。

那么,哪一个更安全呢?好吧,如果"safe"表示"如果强制转换无效,则不会引发异常",那么as形式更安全。如果铸造失败,(MyType)myObject会立即爆炸,但只有当你试图对foo做一些你不能对null做的事情(例如调用InvalidCastException0)时,myObject as MyType才会爆炸。

另一方面,有时抛出异常是最安全的做法。如果您的代码中有错误,您可能想立即知道。如果myObject总是被期望为MyType,那么转换失败意味着某个地方存在错误。如果您继续执行强制转换,那么突然之间,您的程序正在处理垃圾数据!它可能会进一步爆炸,使调试变得困难,或者——更糟的是——它可能根本不会爆炸,只是悄悄地做你意想不到的事情。这可能会造成各种破坏。

因此,这两种形式都不是本质上安全或正确的,它们只是对不同的事情有用。如果:,您将使用myObject as MyType表格

  1. 你不知道myObject是什么类型
  2. 您想使用myObject执行某些操作,但前提是它的类型为MyType
  3. myObject可能不是MyType,这并不意味着存在错误

一个例子是,当你有一个不同的WebForm控件的集合,并且你想清除其中的所有文本框:

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

这样,你的文本框就被清空了,其他的东西就不用管了。

DataTable table = dataSource as DataTable;

如果施放不成功,使用as会返回null,所以不会爆炸。-这意味着您必须在代码的其余部分中处理tablenull的情况。

as不会爆炸,但如果强制转换失败,变量将设置为null。你需要检查一下那个箱子。

DataTable table = dataSource as DataTable;
if (table == null)
{
    // handle case here.
}

如果这就是你所说的"安全",它不会抛出异常。但是,如果强制转换失败,table将为null。

DataTable table = dataSource as DataTable;

如果强制转换失败,则不引发异常。将改为null。

DataTable table = (DataTable)dataSource;

如果强制转换失败,将引发异常。

在这方面是安全的,但是如果强制转换可能失败,那么添加一个null检查来处理它。

这是一种安全的强制转换方式,因为它不会导致异常。然而,如果你不小心,它可能会导致隐藏的错误。

使用as时,如果强制转换失败,则生成的变量为null。如果您不检查这一点,那么稍后当您尝试访问变量时,您将得到一个NullReferenceException,并且它失败的原因将不太清楚(例如,它是null,因为强制转换失败还是后来做了其他事情导致它为空)

如果强制转换无效,"as"运算符不会引发异常。它只是返回null。()方法将引发异常。所以要回答你的问题,这是最安全的方法。

以下是你需要采取的基本方法:

if( x is MyType )
{
   MyType y = (MyType) x;
}

MyType y = x as MyType;
if( y != null )
{
   // Do stuff
}

取决于您要做什么:

DataTable table = dataSource as DataTable;
if (table != null) ...

意思是"dataSource可能DataTable,我要检查它不是null。"

DataTable table = (DataTable) dataSource;

意思是"dataSource应该肯定DataTable,如果不是,那就大错特错了"。

使用as和普通强制转换的区别在于,如果无法执行强制转换(因为对象类型不对),as运算符将返回null。正常的强制转换将引发异常。

所以他们都是"安全的"——当演员阵容无法成功时,他们会有不同的行为。

如果dataSource可以被转换为DataTable,那么它就可以安全地完成任务。但如果你担心它不能成功转换,你可以先检查dataSource。GetType()等于您试图将其强制转换为的类型。

如果您使用as,则不会出现运行时InvalidCastException,但表可能为null,因此需要进行检查。