什么是C#相当于C ++的dynamic_cast?

时间:2012-02-16 17:36:43

标签: c# c++ casting

此C ++代码检查o是否为Node *,如果是,则调用d上的方法。

if (Node * d = dynamic_cast<Node *>(o)) d->do_it();

在C#中编写等效文件的最短和/或最有效的方法是什么?

4 个答案:

答案 0 :(得分:20)

假设Nodeclass,请执行以下操作

Node d = o as Node;
if (d != null) {
  d.do_it();
}

如果它是struct,那么试试这个

if (o is Node) {
  ((Node)o).do_it();
}

答案 1 :(得分:1)

如果as不是o,则Node运算符返回null:

Node d = o as Node;
if (d != null)
{
    d.do_it();
}

答案 2 :(得分:1)

从C#6(2015年7月)开始,假设Nodeclass(或Nullable<T>string等),请使用您的示例

  1. 检查o是否为Node(实际上与将o 转换为 Node并不相同-请参阅有关投射vs在下面转换)
  2. 如果是,请致电do_it()
  3. 立即丢弃强制转换值

您可以使用null-conditional operator

(o as Node)?.do_it();

此语法还可以处理o实际上被声明为Node但恰好是null的情况。

如果要保留转换变量,从C#7(2017年3月)开始,可以运行:

if (o is Node node)
{
    node.do_it();
}

此时变量nodeif语句之外的范围内,等效于:

Node node = o as Node;
if (node != null) 
{
    node.do_it();
}

因此,如果您只想继续执行 oNode,则可以编写:

if (!(o is Node node)) 
{
    return; // or continue, etc
}

node.do_it();
// ...

注意:即使isfalseo关键字也会始终返回null,即使您直接指定类型然后询问如果该变量是该类型。

string foo = null;
if (foo is string)
{
    // never gets here
    Console.WriteLine(foo);
}

铸造与转换

isas关键字的作用与C ++的dynamic_cast<T>相同:它们将检查指定的类型,子类型或接口,但实际上不会更改内存中的值。他们只是告诉编译器变量上应该使用哪些方法。

C#用户之间存在一个误称,我们可以互换使用“ cast”和“ convert”一词。这可能是由于我们经常知道一个基本类型变量总是一个子类型这一事实,因此我们在纯粹地使用时应使用 convert 语法。强制转换语法:

void Foo(MyBaseType value)
{
    // let's assume `value` will always be a MySubType
    MySubType subTypeValue = (MySubType)value;
}

如果value实际上不是MySubType,则此语法将在运行时抛出。

转换与强制转换的不同之处在于,内存中的值可能会发生变化。考虑intdouble

void Foo()
{
    // implicit converting
    int x = 1;
    double y = x;

    // explicit converting
    y = 1.5;
    x = (int)y;
}

在每种情况下,存储在内存中的文字值都会更改格式。 int始终可以用double表示-永远不会丢失数据,因此有一个已定义的implicit operator可以将内存中的数据处理成新的格式。 double s是浮点值且范围大于int s,不能保证不会丢失数据,因此C#需要通过{{1进行显式转换(通常称为“显式强制转换”) }}向编译器表明我们可以丢失数据。

使用类,我们可以定义自己的隐式和显式运算符,它们将以我们认为合适的方式处理数据。这是 convert cast 之间错误的称谓。

explicit operator

答案 3 :(得分:0)

您可以在C#中使用is关键字。

if (o is Node) 
{

}