c# 4.0的dynamic和动态多分派

本文介绍如何在C#4.0中利用dynamic关键字实现动态多分派,对比之前的访问者模式,演示了具体实例并探讨了dynamic处理null的情况。

  在c#4.0以前的代码中如果需要使用动态多分派(dynamic multi dispatch)的话,通常的一种方式是使用访问者(visitor)模式,因为在c# 3.0及以前是只支持动态单分派(override)和静态多分派(overload),为了实现动态多分派就不得的借助访问者模式(当然也有其他的方法)。

  但是,c# 4.0带来了dynamic关键字,所以,在将来的vs2010里面,可以忘记访问者模式,因为可以更加简单的实现动态多分派了(在不是很关心性能的前提下

  那么先来准备一个类:

ContractedBlock.gifExpandedBlockStart.gifCode
    class Foo
    {
        
public virtual void F(int x)
        {
            Console.WriteLine(
"int");
        }
        
public virtual void F(string x)
        {
            Console.WriteLine(
"string");
        }
        
public virtual void F(dynamic x)// same as object
        {
            Console.WriteLine(
"dynamic");
        }
    }

  接着是来试验一下dynamic:

dynamic x = "";
Foo foo 
= new Foo();
foo.F(x);

  结果是:

string

  然后,来一个继承:

ContractedBlock.gifExpandedBlockStart.gifCode
    class Bar : Foo
    {
        
public override void F(int x)
        {
            Console.WriteLine(
"foo int");
        }
        
public override void F(string x)
        {
            Console.WriteLine(
"foo string");
        }
        
public override void F(object x)
        
// Let's override the dynamic by object, and it seems ok.
        {
            Console.WriteLine(
"foo object");
        }
        
public virtual void F(long x)
        
// create a new overload
        {
            Console.WriteLine(
"foo long");
        }
    }

  再次检验一下dynamic:

 

dynamic x = "";
dynamic y 
= 1L;
dynamic z 
= new object();
Foo foo 
= new Bar();
foo.F(x);
foo.F(y);
foo.F(z);

  结果是:

foo string
foo long
foo object

  可以看到dynamic关键字的输出真是我们想要动态多分派的结果,甚至包括在自类新加上去的overload。

  但是,如果我们传给dynamic一个null,会怎么样哪?

dynamic x = null;
Foo foo 
= new Bar();
foo.F(x);

 

foo string

 

  这个输出有点意外,不过仔细分析就可以发现dynamic的工作原理:

  1、 发现是null,所以淘汰所有参数为非可空值类型的重载(这些显然不能接受一个null)

  2、那么在剩下来的两个方法里面,一个参数是object,一个参数是string,挑选可以传入的并且最严格,也就是string

  这里,还有几个特殊情况,仅仅列举一下,就不一一做例子了:

  1、如果参数为null,并且存在1个所有参数为可空的值类型的重载(例如:int?)那么这个重载最优先

  2、如果参数为null,并且存在多个所有参数为可空的值类型的重载,行为比较古怪:

    以下是仅仅测试byte?,sbyte?,short?,ushort?,int?,uint?,long?,ulong?的情况下得到的数据,其他值类型并未测试:

    byte? 最优先

    sbyte? 仅次于byte? 但是如果有 ulong? 则会出现冲突

    short? 次之, 但是同样如果有 ulong? 则会出现冲突

    ushort? 次之,

    int? 次之,但是如果有 ulong? 则会出现冲突

    uint? 次之,

    long? 与 ulong? 冲突

  3、如果参数为引用类型或null,并且存在多个符合的重载,并且各种参数之间没有任何继承关系,那么行为不确定。

转载于:https://www.cnblogs.com/vwxyzh/archive/2009/07/13/1522880.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值