简体   繁体   English

Func委托(C#)中的out参数修饰符

[英]out parameter modifier in Func delegate (C#)

I'm a beginner in C#, just a question on Func delegate: 我是C#的初学者,只是有关Func委托的一个问题:

public delegate TResult Func<in T,out TResult>(T arg);

I can understand the need to place in keyword before T as we don't want to modify the source input, but what about out before TResult? 我可以理解,需要放置in牛逼前关键字作为我们不想修改源输入,但怎么样out TResult过吗? isn't that out means we need to modify the ouput but why? 那不是意味着我们需要修改输出,但是为什么呢? don't we sometimes just generate the return object on the fly, lets say we have a delegate: 有时候我们不是即时生成返回对象,而是说我们有一个委托:

Func<string, bool> nameFilter = str => str[0] == 'S';

so it checks a string to see if its first character is 'S' then return true or false, so we dynamically return this boolean value, what does out keyword do here? 因此它检查字符串以查看其第一个字符是否为'S',然后返回true或false,因此我们动态返回此布尔值,out关键字在这里做什么? there is nothing nneded to be changed to return? 有什么需要改变的吗?

The Short Answer 简短答案

You rarely need to worry about the in and out keywords in Generic type definitions. 您很少需要担心泛型类型定义中的inout关键字。 A class defined with in / out generic type parameters will usually "just work" when you're consuming it, and I'd wager that most devs will never write such a definition in their own code. 使用in / out通用类型参数定义的类通常在使用时会“正常工作”,我敢打赌大多数开发人员永远不会在自己的代码中编写这样的定义。

The Longer Answer 更长的答案

To get a complete explanation, you should read Covariance and Contravariance and Variance in Delegates . 要获得完整的解释,您应该阅读代表中的 协方差,协方差方差 The rest of my answer is just some illustrative example code. 我剩下的答案只是一些说明性的示例代码。

To simplify the explanation, I'm going explain in and out separately through Action<T> and Func<TResult> instead of Func<T,TResult> . 为了简化说明,我要去解释inout通过分别Action<T>Func<TResult>代替Func<T,TResult>

The examples all use the following two classes: 这些示例都使用以下两个类:

class BaseClass {}
class DerivedClass : BaseClass {}

Covariance: out 协方差: out

For this example, I've mimicked Func<out TResult> , but removed the out (covariance) modifier to demonstrate its effect. 在此示例中,我模仿了Func<out TResult> ,但是删除了out (协方差)修饰符以演示其效果。 Covariance allows us to use a func that returns DerivedType anywhere that expects a func that returns BaseType . 协方差允许我们在任何需要返回BaseType的函数的地方使用返回 DerivedType的函数。

class CovarianceExamples
{
    // This is similar to System.Func<out TResult>(), but with covariance removed
    delegate TResult InvariantFunc<TResult>(); 

    void InvariantFuncExample()
    {
        // Ignore the values of these variables; it's the types that are important
        InvariantFunc<BaseClass> baseFunc = null;
        InvariantFunc<DerivedClass> derivedFunc = null;

        baseFunc = baseFunc; // Allowed
        baseFunc = derivedFunc; // Not allowed; compile error!
    }

    void CovariantFuncExample()
    {
        // Ignore the values of these variables; it's the types that are important
        Func<BaseClass> baseFunc = null;
        Func<DerivedClass> derivedFunc = null;

        baseFunc = baseFunc; // Allowed
        baseFunc = derivedFunc; // Allowed
    }
}

Contravariance: in 对比度: in

For this example, I've mimicked Action<in T> , but removed the in (contravariance) modifier to demonstrate its effect. 在此示例中,我模仿了Action<in T> ,但是删除了in (对比度)修饰符以演示其效果。 Contravariance allows us to use an action that accepts BaseType anywhere that expects an action that accepts DerivedType . 逆变允许我们在期望接受DerivedType的动作的任何地方使用接受 BaseType的动作。

class ContravarianceExamples
{
    // This is similar to System.Action<in T>(T), but with contravariance removed
    delegate void InvariantAction<T>(); 

    void InvariantActionExample()
    {
        // Ignore the values of these variables; it's the types that are important
        InvariantAction<BaseClass> baseAction = null;
        InvariantAction<DerivedClass> derivedAction = null;

        baseAction = baseAction; // Allowed
        derivedAction = baseAction; // Not allowed; compile error!
    }

    void ContravariantActionExample()
    {
        // Ignore the values of these variables; it's the types that are important
        Action<BaseClass> baseAction = null;
        Action<DerivedClass> derivedAction = null;

        baseAction = baseAction; // Allowed
        derivedAction = baseAction; // Allowed
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM