• 协变和逆变随笔


    当使用委托时,一般会出现两种角色:广播者(broadcaster)和订阅者(subscriber)。
    广播者是包含委托字段的类型,它通过调用委托决定何时进行广播。
    而订阅者是方法的目标接收者。订阅者通过在广播者的委托上调用+=和-=来决定何时开始监听而何时监听结束。订阅者不知道也不会干涉其他的订阅者。
    而事件就是正式定义这一模式的语言功能。事件是一种使用有限的委托功能实现广播者/订阅者模型的结构。使用事件的主要目的在于保证订阅者之间不互相影响。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace DelegateDemo
    {
        class Program
        {
            public delegate void ProgressReporter(int percentComplete);
            static void Main(string[] args)
            {
                {
                    //X x = new X();
                    //ProgressReporter p = x.InstanceProcess;
                    //p(99);
                    //Console.WriteLine(p.Target == x);
                    //Console.WriteLine(p.Method);
    
                    //ProgressReporter pt = StaticProcess;
                    //pt(100);
                    //Console.WriteLine(pt.Target);
                    //Console.WriteLine(pt.Method);
                }
                {
                    //int[] values = { 1, 2, 3 };
                    //Util.Transform(values, Square);
                    //foreach (var item in values)
                    //{
                    //    Console.Write(item + " ");
                    //}
                }
                {
                    //适用于引用类型的接口
                    //逆变 协变   逆变可以参考一个词语逆子,故逆变是子=>基, 协变是基 => 子(更具体的类型)
                    //协变 用关键字 out 输出  就是可以输出子类   
                    //逆变 用关键字 in 输入  就是输入参数可以是基类
                    //例子 interface ITestOut<out T>{ T Method();}
                    //例子 interface ITestIn<in <T>{ void Method(T obj);}
                    //事件  事件是一种使用有限的委托功能实现广播着/订阅者模型的结构,使用事件的主要目的在于保证订阅者之间不互相影响
                    //int[] collection = { 4, 5, 6 };
                    //UtilForItrans.TransformAll(collection, new Squarer());
                    //foreach (var item in collection)
                    //{
                    //    Console.Write(item + " ");
                    //}
                }
                {
                    //StringAction sa = new StringAction(ActOnObject);
                    //sa("hello");
                    //ObjectRetriever or = new ObjectRetriever(RetrieveString);
                    //Console.WriteLine(or());
                }
                Console.Read();
    
            }
            delegate object ObjectRetriever();
            delegate void StringAction(string s);
            private static void ActOnObject(object o) => Console.WriteLine(o);
            private static int Square(int arg) => arg * arg;
            static string RetrieveString() => "Hello";
            static void StaticProcess(int percentComplete)
            {
                Console.WriteLine(percentComplete);
            }
        }
    
        class X
        {
            public void InstanceProcess(int percentComplete)
            {
                Console.WriteLine(percentComplete);
            }
        }
        public delegate T Transformer<T>(T arg);
        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]);
                }
            }
        }
    
        public interface ITransformer
        {
            int Transform(int x);
        }
    
        public class UtilForItrans
        {
            public static void TransformAll(int[] values,ITransformer t)
            {
                for(int i = 0; i < values.Length; i++)
                {
                    values[i] = t.Transform(values[i]);
                }
            }
        }
    
        class Squarer : ITransformer
        {
            public int Transform(int x) => x * x;
        }
    
        class Broadcaster
        {
             PriceChangedHandler priceChanged;
            public event PriceChangedHandler PriceChanged {
                add { priceChanged += value; }
                remove { priceChanged -= value; }
            }
        }
        public delegate void PriceChangedHandler(decimal oldPrice, decimal newPrice);
    
        //如果去掉event,不会影响运行结果,但是影响如下:
        //通过重新指派PriceChanged替换其他的订阅者(不用+=运算符)
        //清楚所有的订阅者(将PriceChanged设置位null)
        //通过调用其委托广播到其他的订阅者
        public class Stock
        {
            string symbol;
            decimal price;
            public Stock(string symbol)
            {
                this.symbol = symbol;
            }
    
            public event PriceChangedHandler PriceChanged;
    
            public decimal Price {
                get {
                    return price;
                }
                set {
                    if (price == value) return;
                    decimal oldPrice = price;
                    price = value;
                    if(PriceChanged != null)
                    {
                        PriceChanged(oldPrice, price);
                    }
                }
            }
    
        }
    }
  • 相关阅读:
    服务端跳转和客户端跳转的区别
    jsp:include标签与include指令的区别
    jsp错误页不跳转显示500
    使用Cookie进行会话管理
    深入理解重定向和转发
    appium环境搭建(二)----搭建android开发环境
    appium环境搭建(一)----安装appium
    Fiddler实现移动端手机抓包
    黑盒测试人员必备技能
    SVN服务器搭建
  • 原文地址:https://www.cnblogs.com/morec/p/11904268.html
Copyright © 2020-2023  润新知