我是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关键字在这里做什么?有什么需要改变的东西可以退货吗?
答案 0 :(得分:5)
您几乎不需要担心Generic类型定义中的in
和out
关键字。使用in
/ out
泛型类型参数定义的类通常在使用时会“正常工作”,我敢打赌大多数开发人员永远不会在自己的代码中编写这样的定义。
要获得完整的解释,您应该阅读Covariance and Contravariance和Variance in Delegates。我剩下的答案只是一些说明性的示例代码。
为简化说明,我将分别通过Action<T>
和Func<TResult>
而不是Func<T,TResult>
来解释in
和out
。
所有示例均使用以下两个类:
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
}
}