如何使用lambda表达式?

10

我希望在一个字典中保存一组函数,它们都是从某个基本类型继承而来(举个例子,我们可以称这个基类为“object”)。所以,是否有可能将f1保存在f2中呢?

Func<bool> f1 = () => true;
Func<object> f2 = f1;

错误1:无法将类型为System.Func<bool>的内容隐式转换为类型为System.Func<object>的内容。

这是我们能做的最好吗?

Func<bool> f1 = () => true;
Func<object> f2 = () => (object)f1;

错误:(无)

我猜它需要一个where语句来使其更加通用,但我不确定你能否用lambda实现这一点。


在跟进Armen的信息后,我深入了解了字符串和布尔值的定义:

public sealed class String : IComparable, ICloneable, IConvertible, IEnumerable,
                             IComparable<String>, IEnumerabl<char>,
                             IEquatable<String> 

public struct Boolean : IComparable, IConvertible, IComparable<Boolean>,
                        IEquatable<Boolean>

在引用与值方面,他是正确的。 String是否会隐式地从对象继承?根据@ PeterK的链接,似乎对于结构体来说就是这种行为。

"ValueType使用更适合值类型的实现重写了来自Object的虚拟方法。还可以查看继承自ValueType的Enum。"

对象:

System.Object:所有类、结构、枚举和委托。(来自http://msdn.microsoft.com/en-us/library/system.object)

这反过来使得将Func<bool>赋值给Func<object>有点愚蠢。即从那个角度来看,继承层次结构是正确的。


1
Func<object> f2 = () => (object)f1; 应该改为 Func<object> f2 = () => (object)f1(); - leppie
1
@sgtz:(object)f1 仅返回委托,而您从未调用它。 - leppie
@sgtz:不,这很明显... - leppie
@leppie:有时你会听到语言团队在CLR上实现构造方面遇到困难。我对这种纯粹的V和我们所做的近似类型事物很感兴趣。顺便说一句:我查看了你的网站,似乎你不介意进行一些反向工程/挖掘核心转储。并非每个人都有那样的深度(如果我错了,请读者指出)。无论如何,编译器所做的并不完全是我目前作为语言设计师所关注的话题。谢谢。 - sgtz
@leppie:这对社区有什么好处?你的目标是什么?对于你的问题,答案是肯定的,有测试用例。我很乐意重新表述问题以反映任何被认为省略的内容。我很感激您的评论,但不喜欢您言辞中的尖刻之处。说“不言自明”通常是教授会做的事情。稍微放松一下,有些人想保持好奇心。 - sgtz
显示剩余6条评论
2个回答

3
如果您使用的是.NET 4.0以上版本,这是可行的。
您的示例无法正常工作,因为bool是值类型。但是,如果您将bool更改为string,则示例可以工作。
    Func<string> f1 = () => "true";
    Func<object> f2 = f1;

@PeterK. 错误。它们确实有区别。 - Konrad Rudolph
有点奇怪,结构体从 ValueType 派生,而 ValueType 又从 object 派生。我正在努力理解这一点。感谢您的澄清。 - sgtz

3

来自这里(我强调):

协变性使您能够使用比泛型参数指定的更派生的类型。这允许实现变体接口的类的隐式转换和委托类型的隐式转换。协变性和逆变性支持引用类型,但不支持值类型

另外

变异仅适用于引用类型;如果为变体类型参数指定值类型,则该类型参数对于生成的类型是不变的。

原因可能与C#和CLI如何历史性地处理(并且不一致)值类型数组的协变性有关。查看此处了解一些信息。

所以你看,Func<out TResult> 中类型参数的协变性不适用于值类型,因此你需要这样做:
Func<object> f2 = () => f1();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接