C# 为变量分配一个返回匿名类型的函数委托

C# 为变量分配一个返回匿名类型的函数委托,c#,delegates,anonymous-types,lambda,C#,Delegates,Anonymous Types,Lambda,以下代码有效: IEnumerable<SomeThing> things = ...; // map type SomeThing to a new anonymous type, resulting in a strongly typed // sequence based on an anon type var newList = things.Select(item => { return new {

以下代码有效:

IEnumerable<SomeThing> things = ...;

// map type SomeThing to a new anonymous type, resulting in a strongly typed 
// sequence based on an anon type

var newList = things.Select(item =>
    {
        return new
        {
            ID = item.ID,
            DateUpdatedOrCreated = ((DateTime)(item.DateUpdated ??
                     item.DateCreated)).ToShortDateString(),
            Total = item.Part1 + item.Part2
        };
    });
我得到错误“无法将lambda表达式分配给隐式类型的局部变量”。这似乎是一个奇怪的编译器限制;除非我遗漏了什么,否则第二个示例中的类型与第一个示例中的类型一样没有歧义:两个类型参数都定义得很好

有没有办法做到这一点?由于它是一个匿名类型,当然,我没有任何方法可以使用类型显式地分配它,因此,如果没有,我似乎只能为输出类型创建一个类

更新

在用Jon Skeet的答案畅所欲言之后不久,我发现了一个类似的难题:实例化类。如果不明显,可以使用相同的技巧使用推断的匿名类型创建强类型类

class Processor<T,U>
{
    public Processor(Func<T,U> func) {

    }
}

// func is a delegate with anon return type created using method in answer below

var instance = new Processor(func);   // does not compile! Requires type arguments!
类处理器
{
公共处理器(Func Func){
}
}
//func是一个委托,使用下面答案中的方法创建了一个非返回类型
var实例=新处理器(func);//不编译!需要类型参数!
无法直接创建,但可以使用与以下技巧大致相同的方式创建:

public static Processor<T,U> Create<T,U>(Func<T,U> func) {
    return new Processor<T,U>(func);
}

var instance = Processor.Create(func);   // all good
公共静态处理器创建(Func Func){ 返回新处理器(func); } var instance=Processor.Create(func);//一切都好
您可以通过类型推断来完成:

var func = BuildFunc((SomeThing item) => {
    return new { ... };
});

...

static Func<TSource, TResult> BuildFunc<TSource, TResult>(
    Func<TSource, TResult> function) {
    return function;
}
var func=BuildFunc((某物项)=>{
返回新的{…};
});
...
静态函数BuildFunc(
Func函数){
返回函数;
}

请注意,
BuildFunc
实际上并没有做任何事情-它只提供了让编译器对
Func
的泛型类型参数进行类型推断所需的方法调用-它添加了您感兴趣的信息
Func
,基本上-在不指定类型参数的情况下,不能将这些信息指定为变量声明的一部分。

这是有效的,因为泛型的类型推理比
var的类型推理更智能。(我想乔恩也许能解释为什么,尽管我不能。)回答得好。附加信息:这是因为您不需要在此处指定变量的类型。编译器不能仅仅推断变量的类型,因为它可以从多个委托类型中进行选择。@Servy:这并不是更聪明的问题,而是能够指定您想要一个
Func
委托,而是一般地指定它。这太棒了!它工作得很好。我仍然有点惊讶,编译器在没有任何帮助的情况下理解复杂的情况,而不是简单的情况,但这足够简单,而且比创建一个单一用途的类要好得多。好的,我理解为什么linq查询可以工作,而这不能工作,但是编译器不只是假设
Func
委托,有什么理由吗?将其分配给其他什么是有效的?
var func = BuildFunc((SomeThing item) => {
    return new { ... };
});

...

static Func<TSource, TResult> BuildFunc<TSource, TResult>(
    Func<TSource, TResult> function) {
    return function;
}