C#中的is与as运算符和typeof运算符

一、is与as运算符和typeof运算符

1.1、is运算符

  is 运算符检查一个对象是否兼容于其他指定的类型,并返回一个Bool值:

①如果一个对象是某个类型或是其父类型的话就返回为true,否则的话就会返回为false。永远不会抛出异常。
②如果对象引用为null,那么is操作符总是返回为false,因为没有对象可以检查其类型。

1.2、as运算符

  as 运算符将表达式结果显式转换为给定的引用或可以为 null 值的类型。 如果无法进行转换,则 as 运算符返回 null。 与强制转换表达式 不同, 运算符永远不会引发异常

1.3、typeof运算符

  typeof 运算符用于获取某个类型的 System.Type 实例。 typeof 运算符的实参必须是类型或类型形参的名称。

注意:

    C#是一门强类型语言,一般情况下,我们最好避免将一个类型强制转换为其他类型,但有些时候难免要进行类型转换。

其中C#关于类型转换一般我们有以下选择:

①使用as操作符转换;

②使用传统C风格的强制转型;

③使用is来做一个转换测试,然后再使用as操作符或者强制转;

    在编程过程中我们应该尽可能地使用as操作符,因为它比强制转型要安全,而且在运行时层面也有比较好的效率(注意的是as和is操作符都不执行任何用户自定义的转换,只有当运行时类型与目标转换类型匹配时,它们才会转换成功).

二、is运算符

2.1、is运算符的形式

    is 运算符的形式如下:

E is T

其中 E 是返回一个值的表达式,T 是类型或类型参数的名称。 E 不得为匿名方法或 Lambda 表达式。

如果表达式结果为非 null 并且满足以下任一条件,则 is 运算符将返回 true

  • 表达式结果的运行时类型为 T

  • 表达式结果的运行时类型派生自类型 T、实现接口 T,或者存在从其到 T 的另一种T

  • 表达式结果的运行时类型是基础类型为 且 Nullable<T>.HasValue 为 true 的可为空值类型

  • 存在从表达式结果的运行时类型到类型 的装箱取消装箱转换。

is 运算符不会考虑用户定义的转换。

2.2、is运算符典型示例

《1》如果表达式结果的运行时类型派生自给定类型,即类型之间存在引用转换,is 运算符将返回 true

public class Base { }

public class Derived : Base { }

public static class IsOperatorExample
{
    public static void Main()
    {
        object b = new Base();
        Console.WriteLine(b is Base);  // output: True
        Console.WriteLine(b is Derived);  // output: False

        object d = new Derived();
        Console.WriteLine(d is Base);  // output: True
        Console.WriteLine(d is Derived); // output: True
    }
}

 《2》is 运算符将考虑装箱和取消装箱转换,但不会考虑is

int i = 27;
Console.WriteLine(i is System.IFormattable);  // output: True

object iBoxed = i;
Console.WriteLine(iBoxed is int);  // output: True
Console.WriteLine(iBoxed is long);  // output: False

《3》 is 运算符还会对照某个模式测试表达式结果

int i = 23;
object iBoxed = i;
int? jNullable = 7;
if (iBoxed is int a && jNullable is int b)
{
    Console.WriteLine(a + b);  // output 30
}

三、as运算符

3.1、as运算符的形式

    as运算符的形式如下:

E as T

其中,E 为返回值的表达式,T 为类型或类型参数的名称,生成相同的结果。

《1》as 运算符仅考虑引用、可以为 null、装箱和取消装箱转换。 不能使用 as 运算符执行用户定义的转换。 为此,请使用强制转换表达式

IEnumerable<int> numbers = new[] { 10, 20, 30 };
IList<int> indexable = numbers as IList<int>;
if (indexable != null)
{
    // output: 40
    Console.WriteLine(indexable[0] + indexable[indexable.Count - 1]); 
}

3.2、强制转换表达式

    形式为 (T)E 的强制转换表达式将表达式 E 的结果显式转换为类型 T如果不存在从类型 E 到类型 T 的显式转换,则发生编译时错误(需要配合try catch finally来处理,效率较低)。 在运行时,显式转换可能不会成功,强制转换表达式可能会引发异常。

下面的示例演示显式数值和引用转换:

double x = 1234.7;
int a = (int)x;
Console.WriteLine(a);   // output: 1234

IEnumerable<int> numbers = new int[] { 10, 20, 30 };
IList<int> list = (IList<int>)numbers;
Console.WriteLine(list.Count);  // output: 3
Console.WriteLine(list[1]);  // output: 20

四、typeof运算符

4.1、typeof基础

  typeof 运算符用于获取某个类型的 System.Type 实例。 typeof 运算符的实参必须是类型或类型形参的名称,如以下示例所示:

void PrintType<T>() => Console.WriteLine(typeof(T));

Console.WriteLine(typeof(List<string>));
PrintType<int>();
PrintType<System.Int32>();
PrintType<Dictionary<int, char>>();
// Output:
// System.Collections.Generic.List`1[System.String]
// System.Int32
// System.Int32
// System.Collections.Generic.Dictionary`2[System.Int32,System.Char]

参数不能是需要元数据注释的类型。 示例包括以下类型:

  • dynamic
  • string?(或任何可为 null 的引用类型)

    这些类型不会直接在元数据中表示出来。 这些类型包括描述基础类型的属性。 在这两种情况下,都可以使用基础类型。 可以使用 object 来代替 dynamic。 可以使用 string 来代替 string?

你还可以使用具有未绑定泛型类型的 typeof 运算符。 未绑定泛型类型的名称必须包含适当数量的逗号,且此数量小于类型参数的数量。 以下示例演示了具有未绑定泛型类型的 typeof 运算符的用法:

Console.WriteLine(typeof(Dictionary<,>));
// Output:
// System.Collections.Generic.Dictionary`2[TKey,TValue]

表达式不能为 typeof 运算符的参数。 若要获取表达式结果的运行时类型的 System.Type 实例,请使用 Object.GetType 方法。

 4.2、typeof示例

    使用 typeof 运算符来检查表达式结果的运行时类型是否与给定的类型完全匹配。 以下示例演示了使用 typeof 运算符和 typeof执行的类型检查之间的差异:

public class Animal { }

public class Giraffe : Animal { }

public static class TypeOfExample
{
    public static void Main()
    {
        object b = new Giraffe();
        Console.WriteLine(b is Animal);  // output: True
        Console.WriteLine(b.GetType() == typeof(Animal));  // output: False

        Console.WriteLine(b is Giraffe);  // output: True
        Console.WriteLine(b.GetType() == typeof(Giraffe));  // output: True
    }
}

五、is与as运算符使用场景

is与as运算符的使用场景
序号is与as运算符的使用场景
1Object => 已知引用类型——使用as操作符完成
2Object => 已知值类型——先使用is操作符来进行判断,再用类型强转换方式进行转换;
3已知引用类型之间转换——首先需要相应类型提供转换函数,再用类型强转换方式进行转换
4已知值类型之间转换——最好使用系统提供的Convert类所涉及的静态方法
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值