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

时间:2019-03-07 01:06:41

标签: c# .net

我是C#的初学者,只是有关Func委托的一个问题:

%__objc_ivar__DATAp+†$p+__objc_data__DATAP SP__data__DATA0£ê0£__bss__DATA¿º†__common__DATA

由于我们不想修改源输入,因此我理解有必要将public delegate TResult Func<in T,out TResult>(T arg); 放在T之前,但是将in放在TResult之前呢?那不是意味着我们需要修改输出,但是为什么呢?有时候我们不是即时生成返回对象,而是说我们有一个委托:

out

因此它检查字符串以查看其第一个字符是否为'S',然后返回true或false,因此我们动态返回此布尔值,out关键字在这里做什么?有什么需要改变的东西可以退货吗?

1 个答案:

答案 0 :(得分:5)

简短答案

您几乎不需要担心Generic类型定义中的inout关键字。使用in / out泛型类型参数定义的类通常在使用时会“正常工作”,我敢打赌大多数开发人员永远不会在自己的代码中编写这样的定义。

更长的答案

要获得完整的解释,您应该阅读Covariance and ContravarianceVariance in Delegates。我剩下的答案只是一些说明性的示例代码。

为简化说明,我将分别通过Action<T>Func<TResult>而不是Func<T,TResult>来解释inout

所有示例均使用以下两个类:

class BaseClass {}
class DerivedClass : BaseClass {}

协方差:out

在此示例中,我模仿了Func<out TResult>,但是删除了out(协方差)修饰符以演示其效果。协方差使我们可以在希望返回DerivedType的函数的任何地方使用返回 BaseType的函数。

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
    }
}

矛盾度:in

在此示例中,我模仿了Action<in T>,但删除了in(对比度)修饰符以演示其效果。求逆允许我们在希望接受BaseType的动作的任何地方使用接受 DerivedType的动作。

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
    }
}