2013-04-08 4 views
3

У меня есть метод, написанный в терминах типов T и KПередача общего типа, как T

public K Process<T,K> (IEnumerable<T> set) 
{ 
    //do stuff to set 
} 

я использую LINQ, чтобы получить некоторую проекцию моих данных и мне нужно, чтобы отправить его для обработки

var dataSlice=records.Select(r => new { name = r.GetName(), id = r.GetId() }); 
string result = Process <?, string>(dataSlice); 

Что я должен указать? (Если это может быть сделано)

+2

Ну, как на земле «Процесс» должен знать, как извлечь «K» из вашего набора? Если вы предоставите эту информацию, она, вероятно, будет в форме, где будет выполняться вывод типа ... –

+0

При использовании анонимных типов вы не можете явно указывать аргументы типа, поскольку один из типов не имеет имени (является анонимным). Вам придется полагаться на вывод типа и полностью опускать аргументы типа, а это значит, что вам нужно найти другой способ указать аргумент второго типа. (Это в основном парафраз того, что уже сказал @JonSkeet.) – cdhowie

+0

Просто интересно - что вы делаете внутри этого метода Процесса? Вернет ли он DateTime, если я назову его 'Process (arrayOfIntegers)'? –

ответ

1

Вы не можете напрямую, потому что dataSlice теперь коллекция анонимных типов, вы можете попробовать оставить информацию о типе из:

string result = Process(dataSlice); 

Иногда компилятор может выводить правильные типы для вас это экономит печатание и может быть полезно!

Если это не сработает, возможно, вам лучше не использовать анонимный тип и создать правильный тип для хранения данных или использовать что-то вроде Tuple.

Анонимные типы отличные, но они в основном используются для передачи данных между запросами linq, не прибегая к пользовательским типам.

Несмотря на то, что даже если вы могли бы пройти мимо компилятора, ваш метод Process не будет знать, что он получает, и поэтому он не сможет извлечь элемент из dataSlice, поэтому лучше всего пойти по маршруту нестандартного типа или используйте Tuple, как указано ранее.

+0

На самом деле мой метод Process также принимает меры, которые описывают, как обрабатывать dataSlice. Это сработало. Спасибо. – AstroSharp

0

Короткий ответ заключается в том, что вы не можете без перепроектирования своего метода. C# вы должны либо указать все параметры типа, либо none.

Один из вариантов заключается в том, чтобы обернуть ваш метод Process в отдельный API.

public class Processor<T> 
{ 
    public K Process<K>() { ... } 
} 

... 

public Processor<T> CreateProcessor<T> (IEnumerable<T> set) 
{ 
    return new Processor<T>(set) 
} 

... 

string result = CreateProcessor(dataSlice).Process<string>(); 

Вот альтернатива, хотя это немного менее интуитивным, IMO:

public static class Process<K> 
{ 
    public static K From<T>(Ienumerable<T> set) { ... } 
} 

... 

string result = Process<string>.From(dataSlice); 
+3

Я считаю, что метод расширения по-прежнему требует наличия двух общих аргументов. –

+0

@lazyberezovsky да, вы правы, я обновил свой ответ альтернативой –

1

Мне нравится этот простой инструмент:

public static class Klass 
{ 
    public static Klass<T> Of<T>(){ return Klass<T>.instance; } 
} 

public class Klass<T> 
{ 
    public static Klass<T> instance = null; 
} 

и теперь вы можете:

public K Process<T,K>(Klass<T> t, IEnumerable<K> items) 
{ 
    .... 
} 

var aKey = Process(Klass.Of<string>(), mySetOfItems); 
// aKey will be autotyped to a string 

, но учтите, что для этого потребовалось доработать d для метода процесса. Этот параметр используется исключительно для устранения отсутствующего типа. Вот почему «экземпляр» всегда равен нулю. Значение не важно, все, что считается, это то, что этот null имеет тип Klass.

Однако обратите внимание, что этот 100% -ый ресурс избавляет вас от использования явных параметров типа, например, в Process<string, ....>, потому что вам не нужно явно проезжать параметр типа <string>. Таким образом, все параметры типа привязаны к аргументам, и это позволяет копилеру автоматически разрешать анонимные типы, включая элемент IEnumerable.

Редактировать: Я только что вспомнил о еще одной вещи, хотя и более сложной и сложной. Анонимные типы полностью устаревают. Это означает, что один анонимный тип с «string Key, int Value» является абсолютно тем же классом, что и второй анонимный тип, созданный в другом месте, который также является «string Key, int Value». Это позволяет создать небольшой вспомогательный метод, описанный здесь CastByExample.

Как правило, вы не можете «указать» анонимный тип, потому что, ну, это неназванный, и вы не можете записать его имя. Но, благодаря дактилизму, эта драгоценная статья показывает, как вы можете обеспечить никогда не исполняемую лямбду, которая возвращает «образец» анонимного объекта только для того, чтобы перехватить анонимный тип, который он определяет, чтобы этот тип можно было передать цепочка выражений. Очень угловой, но интересная вещь!

+0

@JGinSD: огромное спасибо за патч, действительно забыл статическое ключевое слово. – quetzalcoatl

+0

Это гениальный взлом! – usr

+0

@usr: thank you :) Я вспомнил еще об одной вещи, вы можете также проверить эту статью, отличную от примера. – quetzalcoatl

Смежные вопросы