2012-05-09 57 views
6

下面的代碼是有效的:現在分配函數委託,它返回一個匿名類型的變量

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

newList在Visual Studio中顯示爲IEnumerable<'a>,並在函數創建的匿名類型是強類型。太酷了。

我似乎無法做的是找出一種方法來分配一個隱式類型變量的lambda表達式(而不是枚舉)。即使編譯器具有與上下文中的上述匿名類型沒有什麼問題,如果我嘗試(比方說)

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

我得到錯誤「無法分配lambda表達式隱式類型的局部變量」。這似乎是一個奇怪的編譯器限制除非我缺少一些東西,否則第二個示例中的類型與第一個示例中的類型無關,這兩個類型參數都已定義好。

有沒有辦法做到這一點?由於它是一個匿名類型,當然,我沒有任何方法可以使用類型來明確地指定它,所以看起來我會堅持爲輸出類型創建一個類,如果沒有的話。

更新

去一下我的喬恩斯基特的答案快樂的方式後不久,我發現了一個類似的窘境實例化類。如果不明顯,則可以使用相同的技巧來使用推斷的匿名類型來創建強類型類。

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! 

不能直接創建,但可以在幾乎相同的方式,如下竅門創建:

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 

回答

8

您可以通過類型推斷做到這一點:

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

... 

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

注意BuildFunc並沒有真正做任何事情 - 它只是提供方法調用,以使編譯器對Func<,>的泛型類型參數進行類型推斷 - 它添加了信息tha你有興趣在Func<,>,基本上 - 這是信息不能被指定爲變量聲明的一部分,也沒有指定類型參數。

+0

這適用,因爲泛型的類型推斷比'var'的類型推斷聰明。 (我認爲jon可能能夠解釋爲什麼即使我不能。) – Servy

+0

很好的答案。附加信息:這是可行的,因爲你不需要在這裏指定變量的類型。編譯器不能僅僅推斷變量的類型,因爲它有多個可以選擇的委託類型。 – usr

+0

@Servy:這不是一個聰明的問題 - 它可以指定你想要一個'Func'委託,但是一般地指定它。 –