2009-07-31 4 views
14

У меня есть метод объекта, который является чем-то вроде фабрики. Вы даете ему тип, он создает экземпляр и делает несколько других вещей. Элегантный способ сделать это (на мой взгляд), как это:Как передать тип метода - аргумент типа vs generics

public T MagicMethod<T>() where T: SomeBaseClass 
{ 
    // Magic goes here 
} 

Но это расстраивает FxCop, кто говорит, что это плохой стиль - я получаю «CA1004: Общие методы должны обеспечить параметр типа» предупреждение. Что-то не в том, чтобы использовать выводы и прочее. Таким образом, единственным способом я могу думать что-то вроде этого:

public SomeBaseClass MagicMethod(Type T) 
{ 
    // Same magic goes here 
} 

Я считаю, что это уступает первому методу по многим счетам, но правило стиля ... В статье MSDN на предупреждение даже говорит что нет причин для его подавления.

Я делаю это правильно, подавляя это предупреждение в конце концов?

+0

Совершенно неправильно ваш вопрос, так что я имею удалил мой ответ. –

+1

В порядке, так как я никогда не видел вашего ответа.:) –

ответ

3

FXCop предупреждения только что - предупреждения. Как и скрытые предупреждения о броске, они служат для того, чтобы вы знали, что что-то, что вы делаете, может иметь поведение, которого вы не ожидаете, или, возможно, не то, что вы намеревались.

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

То же самое с FXCop. Посмотрите на предупреждение, посмотрите на свой код и определите, действительно ли предупреждение. Если это так, исправьте. Если нет, подавите его. Подавление является эквивалентом явного приведения - «Да, FXCop, я уверен, что я хочу это сделать».

Если это действительно действительно ошибка, вероятно, это ошибка компилятора.

+6

Да, но на странице MSDN с подробностями об этом предупреждении явно указано, что «вы не должны подавлять это предупреждение». Честно говоря, я умнее, чем коллективная мудрость команды FXCop? –

0

Второй подход даже не эквивалентен первому. Во втором вам буквально задан тип, но вы не можете создать экземпляр объекта такого типа (если вы не используете Reflection --- eeek!), И вам нужно явно объявить тип возврата (который побеждает цель дженериков в Начать с).

См. this примечание о его подавлении. Похоже, это нормально подавлять.

EDIT: Теперь вот еще одна идея. Что, если вы изменили его на параметр «out» и не вернули его через возвращаемую переменную? Изменит ли это предупреждение?

public void MagicMethod<T>(out T retVar) where T: SomeBaseClass 
{ 
    // Magic goes here 
} 
+0

Наверное, но это было бы не очень удобно использовать. :) –

+0

Правда, не могу винить вас в этом. –

0

Лично я беспокоился бы о большинстве предупреждений в Fxcop.

Вы, кажется, знаете, что вы делаете, почему некоторые автоматизированные части программного обеспечения знают лучше?

Ну, это не возможно, это догадка.

+1

Ну, я подумал, что гораздо более талантливые и опытные разработчики, чем я, написали этот инструмент, и если они скажут, что я не должен этого делать, возможно, я не должен. :) –

15

Я считаю, что вы не понимаете, что говорит вам FxCop, возможно, потому, что его формулировка не идеальна. Это означает, что общий метод должен обеспечивать параметр, который имеет такой тип, а не то, что общий метод должен иметь неосновную перегрузку, которая предоставляет экземпляр времени выполнения Type. Например,

public void DoSomething<T>(T myParam); 

The myParam является своего рода показателем он имеет в виду. Причина, по которой это требуется, - это, как вы полагаете, для вывода. Это позволяет сделать что-то вроде ...

string foo = "bar"; 

DoSomething(foo); 

вместо того, чтобы написать

DoSomething<string>(foo); 

В вашем случае, это хорошо, чтобы подавить предупреждение, так как вы хотите пользователем явно указать тип. Я бы предположил, однако (при условии, что ваши конструкторы без параметров), что вы меняете свой where на where T : SomeBaseClass, new(). Это означает, что он заставит компилятор потребовать, чтобы какой бы тип не был передан без конструктора без параметров. Это также означает, что вы можете сделать new T() в своем коде.

+0

Ну ... на самом деле, это не совсем конструктор ... он звонит в другую стороннюю библиотеку, где я даю тип как простой параметр типа, а затем строит объект ... Но в любом случае это лишние детали , :) –

5

У меня не было бы проблемы с подавлением этого предупреждения. Для начала эквивалент в собственном коде MS является Activator.CreateInstance<T>()

public static T CreateInstance<T>() 

Это означает, что правило анализа следует учитывать тип возвращения метода, подпадают ли под общим параметром ...

Это было упоминается во многих местах раньше:

И были предыдущие ошибки в правиле, например:

public static void GenericMethod<T>(List<T> arg); 

ранее вызовет его (fixed in 2005 SP1).

Я предлагаю подав соединять ошибки для конкретного примера

+0

Фу. Так что это не только я! :) –

0

Прежде всего, это предупреждение состоит в том, чтобы убедиться, что вызывающие абоненты делают все сознательно. Вы можете вызвать ваш метод без передачи какого-либо параметра типа, потому что компилятор знает тип объекта перед рукой. FxCop говорит вам, чтобы он был неявным, чтобы синтаксис использования общих и не общих перегрузок выглядел одинаково (я не согласен с этим принципом, но это личное и не имеет значения здесь).

Во-вторых, ваш второй метод наносит больше урона, чем вы можете думать прямо сейчас. Там нет проверки типа времени компиляции, поэтому будьте предупреждены о недействительных исключениях выполнения во время выполнения, если вы его используете.

1

FxCop будет срабатывать это предупреждение, даже если вы используете общий параметр типа в одном или более аргументов, если она не «раздели»:

public void LinkedList<T> Slice<T>(LinkedList<T> collection, Predicate<T> match) 
{ 
    ... 
} 

По крайней мере правило «CA1004» выстрелил «в error "здесь на днях по методу с этой подписью.

Для будучи умнее, чем команда FxCop, я не уверен, что правила могут правильно определить код во всех случаях, это то, что уровень доверия для :)

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