C# 中的类型转换与作为运算符 [重复]

Type casting vs as operator in C# [duplicate]

提问人:Ali Kh 提问时间:8/6/2023 更新时间:8/6/2023 访问量:57

问:

C#中的类型转换和as运算符有什么区别。例如,在此代码中:

class LivingThing
{
        public int NumberOfLegs { get; set; }
}
class Parrot : LivingThing
{

}

interface IMover<in T>
{
        void Move(T arg);
}

class Mover<T> : IMover<T>
{
    public void Move(T arg)
    {
       // as operator
       Console.WriteLine("Moving with" + (arg as Parrot).NumberOfLegs + " Legs");
       // Type casting
       Console.WriteLine("Moving with" + (Parrot)arg.NumberOfLegs + " Legs");
    }
}

为什么类型转换在第二种情况下无效,它们有什么区别?

C# .NET 强制转换为 运算符

评论

0赞 Cleptus 8/6/2023
你是说吗?两行不一样,一指,一指。在我看来像一个错别字((Parrot)arg).NumberOfLegsargarg.NumberOfLegs

答:

1赞 Dmitry Bychenko 8/6/2023 #1

  • ((Parrot) arg)cast :抛出实例或异常(无效强制转换)。注意,你应该先投射,然后才使用:注意额外ParrotargNumberOfLegsConsole.WriteLine("Moving with" + ((Parrot)arg).NumberOfLegs + " Legs");(...)
  • arg as Parrot:实例或(请注意,如果类型是,则不能使用,因此不能Parrotnullasstructnull)
  • arg is Parrot:如果可以转换为,要么以其他方式trueargParrotfalse

最后一种情况 () 可用于模式匹配,例如is

Console.WriteLine($"Moving with {(arg is Parrot parrot ? parrot.NumberOfLegs : 0)} Legs");
-1赞 Thomas Gicquel 8/6/2023 #2

类型转换无效,因为您应该这样做

 // ((Parrot)arg).NumberOfLegs
 Console.WriteLine("Moving with" + ((Parrot)arg).NumberOfLegs + " Legs");

区别在于:

  • 类型转换(显式强制转换):(Parrot) 如果 arg 不是 Parrot 或派生自 Parrot 的类型。它不执行任何安全检查。
  • 运算符:as 运算符在引用类型或可为 null 的类型之间执行转换,并且包括安全检查。如果强制转换无效,它将返回 null 而不是引发异常。所以(arg as Parrot)。NumberOfLegs 将尝试将 arg 转换为 Parrot,如果 arg 不是 Parrot,它将返回 null。如果随后尝试访问 NumberOfLegs,则会收到 NullReferenceException。

注意:添加泛型类型约束也是一种很好的做法:https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/where-generic-type-constraint