欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C# 委托补充01

程序员文章站 2023-11-18 19:01:40
上一篇文章写了委托的最基本的一些东西,本篇咱们扯扯委托其他的东西。 示例1插件编程 根据对委托的理解,委托可以把一个方法当作参数进行传递,利用这个特性我们可以使用委托,实现插件编程。 这里的Transform方法就是插件方法,它接受一个委托参数。 示例2多播委托 所有的委托都有多播的能力。这就意味着 ......

上一篇文章写了委托的最基本的一些东西,本篇咱们扯扯委托其他的东西。

示例1插件编程

根据对委托的理解,委托可以把一个方法当作参数进行传递,利用这个特性我们可以使用委托,实现插件编程。

public delegate int transformer(int x);

class util{
    pubilc static void transform(int[] values, transformer t){
        for(int i = 0; i < values.length; i++){
            values[i] = t?.invke(values[i]);
        }
    }
}

class test{
    static void main(){
        int[] values = {1,2,3};
        util.transform(values, sqare);
        
        foreach(int i in values){
            console.writeline(i + " "); //1 4 9
        }
    }
    
    static int sqare (int x) => x * x;
}

这里的transform方法就是插件方法,它接受一个委托参数。

示例2多播委托

所有的委托都有多播的能力。这就意味着一个委托可以引用一个方法,或者引用一个组方法。委托使用 += 和 -=运算符联结多个委托实例。

public class people{}
public class student:people{}
public delegate void action();

class program
{
    static void say(){
        console.writeline("say hi");
    }
    static void write(){
        console.writeline("write anything");
    }
    
    action action = say;
    action += write;//action = action + write;
    action();
    
    /*
        say hi
        write anything
    */
    
    
    
}

委托会按照添加的顺序依次触发。如果存在返回值,那么调用者会将最后一个带有非void返回值类型的方法返回值进行返回,其他的返回值将会抛弃。

- 和-= 运算符会从左侧委托操作数中将右侧的委托操作删除。
对于为值为null的委托执行 + 或者+= 操作,等价于为委托指定一个新的值。同样在当委托只有一个目标方法时,执行-=操作等价于为委托指定null值。
由于委托是一个类,所以委托是不可变,每次执行 += 或者-= 实质上等价于从新创建一个新的委托实例,并为它赋值。
具体使用,比如说我们要建一栋大楼,需要很长一段时间,但是公司有要求每建好一层需要给公司汇报一下。

public delegate void progressreporter(int floor);

public class edifice{
    public static void build(progressreporter p){
        for(int i = 0; i < 18; i++){
            p(i);
            
            system.threading.thread.sleep(1000);//添加点时间
        }
    }
}
class test{
    static void main(){
        progressreporter p = writeprogresstoconsole;
        p += advisetocompany;
        edifice.build(p);
    }
    
    static void writeprogresstoconsole(int fool) => console.writeline($"{fool}层已建成");
    
    static void advisetocompany(int fool) => console.writeline($"**项目,已经建好{fool}层。");
    
    
}

示例3泛型委托

委托类型可以包含泛型类型参数,如:

public delegate t transformer<t> (t t);

通过一个泛型参数,我们可以定义一个通用的transformer,让它对任何类型都有效:

public class util{
    public static void transform<t> (t[] values, transformer<t> t){
        for(int i = 0; i < values.length; i++){
            values[i] = t(values[i]);
        }
    }
}
class test{
    static void main(){
        int[] values = {1,2,3};
        util.transformer(values, square);
        
        foreach(int i in values){
            console.write(i + " "); //1 4 9
        }
    }
    
    static int sqare (int x) => x * x;
    
}

既然委托支持泛型参数,那么就可以定义一些小型的委托类型,它们可以具有任意的返回类型和合理的数目的参数,类如系统定义好的action委托和func委托(out和in标记可变性修饰符,在逆变和协变中有解释)。

delegate void action();
delegate void action<in t> (t arg);
delegate void action<in t1, in t2> (t1 arg1, t2 arg2)
………
delegate tresule func(out tresule)();
delegate tresule func<in t, out tresule> (t arg);
delegate tresule func<in t1, in t2, out tresule> (t1 arg1, t2 arg2)
………

其中action和func 都可以支持16个参数。
上面的transform重写.

public static void transform<t> (t[] values, func<t, t> transformer){
    for(int i = 0; i < values.length; i++){
        values[i] = transformer(values[i]);
    }
}

委托还有很多东西,下次聊!

参考自c#7.0核心技术指南