编写高质量代码改善C#程序的157个建议——建议44:理解委托中的协变

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了编写高质量代码改善C#程序的157个建议——建议44:理解委托中的协变相关的知识,希望对你有一定的参考价值。

 

建议44:理解委托中的协变

委托中的泛型变量天然是部分支持协变的。为什么是“部分支持协变”?看下面示例:

   class Program
    {
        public delegate T GetEmployeeHanlder<T>(string name);

        static void Main()
        {
            GetEmployeeHanlder<Employee> getAEmployee = GetAManager;
            Employee e = getAEmployee("Mike");
        }

        static Manager GetAManager(string name)
        {
            Console.WriteLine("我是经理: " + name);
            return new Manager() { Name = name };
        }

        static Employee GetAEmployee(string name)
        {
            Console.WriteLine("我是雇员: " + name);
            return new Employee() { Name = name };
        }

    }

    interface ISalary<T>
    {
        void Pay();
    }

    class BaseSalaryCounter<T> : ISalary<T>
    {
        public void Pay()
        {
            Console.WriteLine("Pay base salary");
        }
    }

    class Employee
    {
        public string Name { get; set; }
    }
    class Programmer : Employee
    {
    }
    class Manager : Employee
    {
    }

上中的GetAManager返回的是一个Manager,但是在使用中,其实是将其赋值给一个泛型参数为Employee的委托变量。因为存在下面一种情况,所以编译不过:

            GetEmployeeHanlder<Manager> getAManager = GetAManager;
            GetEmployeeHanlder<Employee> getAEmployee = GetAManager;

要让上面的代码编译通过,同样需要为委托中的泛型参数指定out关键字:

public delegate T GetEmployeeHanlder<out T>(string name);

除非考虑到该委托声明肯定不会用于可变性,否则,为委托中的泛型参数指定out关键字将会拓展委托的应用,建议在实际编码过程中永远这样使用。实际上,FCL4.0中的一些委托声明已经用out关键字来让委托支持协变了,如我们常常会使用到的:

public delegate TResult Func<out TResult>();

public delegate TOutput Converter<in TInput, out TOutput>(TInput input);

 

 

 

转自:《编写高质量代码改善C#程序的157个建议》陆敏技

 

以上是关于编写高质量代码改善C#程序的157个建议——建议44:理解委托中的协变的主要内容,如果未能解决你的问题,请参考以下文章

编写高质量代码改善C#程序的157个建议——建议141:不知道该不该用大括号时,就用

编写高质量代码改善C#程序的157个建议——建议55:利用定制特性减少可序列化的字段

编写高质量代码改善C#程序的157个建议——建议52:及时释放资源

编写高质量代码改善C#程序的157个建议——建议41:实现标准的事件模型

编写高质量代码改善C#程序的157个建议——建议111:避免双向耦合

编写高质量代码改善C#程序的157个建议——建议8: 避免给枚举类型的元素提供显式的值