2012-05-09 14 views
6

koduna anonim türünü döndüren bir fonksiyonu temsilci atama geçerlidir:altında bir değişken

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 şimdi IEnumerable<'a> olarak Visual Studio görünür ve güçlü işlevinde oluşturulan anonim türü ile yazılır. Bu çok havalı.

Yapamadığım şey, örtük olarak yazılan bir değişkene lambda ifadesini (ve numaralandırmayı değil) atamanın bir yolunu bulmaktır. derleyici yukarıdaki bağlamda anonim tip bir problemi yok olsa ben

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

(diyelim ki) çalışırsanız, hata "lambda ifadesi yerel değişken örtülü-daktilo atanamıyor" olsun. Bu garip bir derleyici sınırlaması gibi görünüyor; Bir şeyleri kaçırmadığım sürece, türler ilk örnekte olduğu gibi 2. örnekte de belirsizdir: her iki tip parametresi de iyi tanımlanmıştır.

Bunu yapmanın bir yolu var mı? Anonim bir tür olduğu için, tabii ki, onu açıkça atamak için bir tür kullanmanın herhangi bir yolu yok, bu yüzden çıktı türü için bir sınıf yapmamaya takılıyorum.

Güncelleme

kısa bir süre Jon Skeet cevabı ile benim neşeli yolu hakkında gittikten sonra, ben sınıfları başlatmasını benzer bir ikilem bulundu. Açık olmadığı takdirde, aynı hile, anonim türden türetilmiş türler kullanarak güçlü yazılan sınıflar oluşturmak için kullanılabilir.

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! 

doğrudan oluşturulamaz, ancak aşağıda hile olarak hemen hemen aynı şekilde oluşturulabilir:

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 

cevap

8

Sen tür kesmesi ile yapabilirsiniz:

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

... 

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

Not o BuildFunc gerçekten bir şey yapmaz - sadece derleyici Func<,> için genel tür argümanları için tür çıkarsama yapmak için gerekli yöntem çağrısı sağlar - bilgi tha ekler Temel olarak Func<,> ile ilgileniyorsanız, bu tip argümanları belirtmeden, değişken bir bildirimin parçası olarak belirtilemeyen bilgiler.

+0

Bu, jenerikler için tür çıkarımının "var" için tür çıkarımından daha akıllı olması nedeniyle çalışır. (Jon'un neden olmasam da neden olduğunu açıklayabileceğini sanıyorum.) – Servy

+0

İyi cevap. Ek bilgi: Bu, değişkenin türünü burada belirtmeniz gerekmediği için çalışır. Derleyici, yalnızca değişken için bir tür elde edemez çünkü seçilebilecek birden çok delege türü vardır. – usr

+0

@Servy: Aslında böyle daha akıllı olmanın bir meselesi değil - bir 'Func' temsilcisinin olmasını istediğinizi belirtmek, ancak bunu genel olarak belirtmek. –

İlgili konular