C# 'is'运算符与转换为泛型类型之间有什么区别?

C# 'is'运算符与转换为泛型类型之间有什么区别?,c#,nullable,C#,Nullable,为什么第一个函数编译,第二个函数发出警告?这两种实现是否不等价?在两种实现中,valT的类型都是T T到1(对象?val) { 如果(!(val为T valT)) { 抛出新的InvalidCastException(); } 返回谷; } T到2(对象?val) { var valT=(T)val; return valT;//可能的空引用返回 } 前言:您可能不需要实现通用的“Cast”方法。在C#中实现通用方法以提高性能时要小心,以避免装箱(避免使用object)。此外,如果在泛型方法中

为什么第一个函数编译,第二个函数发出警告?这两种实现是否不等价?在两种实现中,
valT
的类型都是
T

T到1(对象?val)
{
如果(!(val为T valT))
{
抛出新的InvalidCastException();
}
返回谷;
}
T到2(对象?val)
{
var valT=(T)val;
return valT;//可能的空引用返回
}

前言:您可能不需要实现通用的“Cast”方法。在C#中实现通用方法以提高性能时要小心,以避免装箱(避免使用
object
)。此外,如果在泛型方法中隐藏了实际的显式cast运算符,那么C#编译器就无法向使用代码发出早期警告,表明cast是可证明不正确的

考虑:

Int32 i = new Int32();
String s = (String)o; // <-- CS0030 Cannot convert type 'int' to 'string'
为什么第一个函数编译,第二个函数发出警告

  • 您的第一个函数使用的是
    is
    运算符,它是安全的,并且永远不会抛出(请注意,在这种情况下,是您的代码抛出
    InvalidCastException
  • 第二个函数盲目使用强制转换表达式,而不首先进行类型检查,因此它是不安全的,因为如果
    T
    不正确,除非操作数
    null
    ,否则运算符本身会抛出
    InvalidCastException

  • foo is T bar
    操作符测试非
    null
    值的类型。如果
    foo
    null
    ,则
    is
    表达式返回false,
    bar
    default(T)
  • T bar=(T)foo
    cast表达式将强制转换
    null
    ,但仅当
    T
    是引用类型时,该语法也可以调用自定义显式转换运算符,而不是执行强制转换


  • 还请注意,C#8.0的可空引用类型功能(
    object?
    )在运行时未强制执行:,因此,如果将代码更改为使用
    object而不是
    object?
    ,则仍应添加
    如果(val为null)抛出新的ArgumentNullException(nameof(val))

    is返回false,而null可以强制转换为T(如果T是引用类型)。尝试将
    null
    传递给两者。
    Int32 i = new Int32();
    String s1 = To1<String>( i ); // No compiler error, despite incompatible types.
    String s2 = To2<String>( i ); // Also no compiler error.
    
    // Using your functions `To1` and `To2`:
    
    String strFromObj  = To1<String>( new Object() ); // throws InvalidCastException (thrown from your code)
    String strFromNull = To1<String>( null         ); // throws InvalidCastException (thrown from your code)
    
    String strFromObj  = To2<String>( new Object() ); // throws InvalidCastException (thrown from the operator)
    String strFromNull = To2<String>( null         ); // returns null;