Как передать тип аргументу типа метода в сравнении с generics

StackOverflow https://stackoverflow.com/questions/1212183

Вопрос

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

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

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

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

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

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

Это было полезно?

Решение

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

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

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

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

Другие советы

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

public void DoSomething<T>(T myParam);

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

string foo = "bar";

DoSomething(foo);

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

DoSomething<string>(foo);

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

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

public static T CreateInstance<T>()

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

Об этом уже упоминалось во многих местах:

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

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

ранее это вызвало бы (исправлено в 2005 году с пакетом обновления 1).

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

FxCop вызовет это предупреждение, даже если вы используете параметр универсального типа в одном или нескольких аргументах, если он не " раздетый ":

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

По крайней мере правило "CA1004" сработало "по ошибке" здесь на днях на метод с этой подписью.

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

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

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

РЕДАКТИРОВАТЬ: Теперь вот еще одна идея. Что если вы изменили его на выходной параметр и не вернули его через возвращаемую переменную? Будет ли это убрать предупреждение?

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

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

Похоже, вы знаете, что делаете, почему некоторые автоматизированные программы знают лучше?

Ну, это не так, это предположение.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top