什么';s是等价于C++的C#;s dynamic_cast
本文关键字:dynamic cast 等价于 什么 C++ | 更新日期: 2023-09-27 18:24:48
此C++代码检查o
是否为Node *
,如果是,则调用d
上的方法。
if (Node * d = dynamic_cast<Node *>(o)) d->do_it();
用C#编写等效代码的最短和/或最有效的方法是什么?
假设Node
是class
,则执行以下
Node d = o as Node;
if (d != null) {
d.do_it();
}
如果是struct
,那么试试这个
if (o is Node) {
((Node)o).do_it();
}
从C#6开始(2015年7月),假设Node
是class
(或Nullable<T>
、string
等),使用
- 检查
o
是否为Node
(实际上与将o
转换为Node
不同——请参阅下面关于强制转换与转换的注意事项) - 如果是,请致电
do_it()
- 立即放弃强制值
您可以使用null条件运算符:
(o as Node)?.do_it();
此语法还处理o
实际上被声明为Node
,但恰好是null
的情况。
如果你想保留强制转换变量,从C#7(2017年3月)开始,你可以运行:
if (o is Node node)
{
node.do_it();
}
此时变量node
在if
语句之外的范围内,相当于:
Node node = o as Node;
if (node != null)
{
node.do_it();
}
因此,如果你只想继续执行,如果o
是Node
,你可以写:
if (!(o is Node node))
{
return; // or continue, etc
}
node.do_it();
// ...
注意:如果o
是null
,则is
关键字将始终返回false
,即使您直接指定类型,然后询问该变量是否为该类型。
string foo = null;
if (foo is string)
{
// never gets here
Console.WriteLine(foo);
}
铸造与转换
is
和as
关键字的作用与C++的dynamic_cast<T>
相同:它们将根据指定的类型、子类型或接口进行检查,但实际上不会更改内存中的值。它们只是告诉编译器应该在变量上使用哪些方法。
C#用户中有一个用词不当的地方,我们可以互换使用"cast"answers"convert"这两个词。这可能源于这样一个事实,即我们经常知道基类型变量总是一个子类型,因此当我们应该使用强制转换语法时,我们使用convert语法:
void Foo(MyBaseType value)
{
// let's assume `value` will always be a MySubType
MySubType subTypeValue = (MySubType)value;
}
如果value
实际上不是MySubType
,则此语法将在运行时抛出。
转换与强制转换的不同之处在于内存中的值可能会发生变化。考虑int
和double
。
void Foo()
{
// implicit converting
int x = 1;
double y = x;
// explicit converting
y = 1.5;
x = (int)y;
}
在每种情况下,存储在内存中的文字值都会更改格式。int
s总是可以用double
来表示——数据永远不会丢失——因此有一个定义的implicit operator
,它将把内存中的数据处理成新的格式。double
s是浮点值,其范围大于int
s,不能保证数据不丢失,因此C#需要通过explicit operator
进行显式转换(通常称为"显式转换"),以向编译器表明我们可以处理数据丢失。
通过类,我们可以定义自己的隐式和显式运算符,这些运算符将以我们认为合适的方式操作数据。这就是convert和cast之间用词不当的地方。
using System;
public class Program
{
public static void Main()
{
Foo foo = new Foo();
Bar bar = (Bar)foo;
// writes "1" (or would, if the program compiled)
Console.WriteLine(bar);
// throws compilation error: "Cannot convert type `Foo' to `Bar' via built-in conversion"
bar = foo as Bar;
// note: the same would happen if `foo` was type int? and `bar` was type `double?`
// even though double? can be converted to int?
}
}
class Foo
{
public readonly int Value = 1;
public static explicit operator Bar(Foo foo)
{
return new Bar(foo.Value.ToString());
}
}
class Bar
{
public readonly string Value;
public Bar(string value)
{
Value = value;
}
}
如果o
不是Node
:,则as
运算符返回null
Node d = o as Node;
if (d != null)
{
d.do_it();
}
您可以在C#中使用is
关键字。
if (o is Node)
{
}