协变和逆变随笔
Posted morec
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了协变和逆变随笔相关的知识,希望对你有一定的参考价值。
当使用委托时,一般会出现两种角色:广播者(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); } } } } }
以上是关于协变和逆变随笔的主要内容,如果未能解决你的问题,请参考以下文章