Методы расширения C# в.NET 2.0

Я нашел несколько ссылок на способы заставить методы расширения работать в.NET2.0 (Moth, Discord & Rhyme, Stack Overflow). Я также смутно слышал от коллеги, что это вызывает некоторые проблемы с библиотеками или что-то в этом роде? Это тот случай? Также все 3 используют разные методы:

Моли:

namespace System.Runtime.CompilerServices
{
  public class ExtensionAttribute : Attribute { }
}

Раздор и Рифма

namespace System.Runtime.CompilerServices
{
  [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
  public class ExtensionAttribute : Attribute {}
}

Переполнение стека

namespace System.Runtime.CompilerServices
{
    [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class
         | AttributeTargets.Method)]
    public sealed class ExtensionAttribute : Attribute {}
}

В чем разница между этими методами, и какой из них вы бы порекомендовали?

5 ответов

Решение

В конечном счете это не будет иметь большого значения; Вы можете утверждать, что тот, который соответствует среде выполнения, предпочтительнее, но идеальным ответом является переключение на.NET 3.5 (в противном случае позже это может привести к путанице с разными версиями одного и того же атрибута в области видимости и т. д.).

[AttributeUsage] предотвратит его привязанность к вещам, где он ничего не будет делать - но он все равно ничего не сделает...

Глядя на метаданные для типа, точное использование атрибута больше всего похоже на вариант stackru - но в конечном итоге это не очень важно - имя и пространство имен - это все, что имеет значение (и что оно наследует от Attribute).

Версия SO является точной, ради точности вы должны использовать ее.

Кстати, спецификатор AttributeTarget.Method предельно ясен. Класс и сборка меньше так. И C#, и компилятор VB.NET выдают атрибут статического класса / модуля, который содержит метод расширения. И на сборке, которая содержит класс / Модуль. Почему они делают это менее ясно, не нужно было бы правильно их компилировать. Я предполагаю, что это оптимизация на работе, помогающая и компилятору, и IntelliSense выяснить, когда следует рассмотреть метод расширения.

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

Разница достаточно проста:

В вашем первом примере вы можете поместить атрибут в любом месте. Во втором примере вы можете применить его только к методу, но не более одного к одному и тому же методу, и унаследованный класс с переопределенным методом не будет наследовать атрибут. В третьем примере вы можете применить его к методу, классу или сборке.

Если вы попытаетесь применить его в любом другом месте, вы получите ошибку компилятора.

Второй, кажется, имеет больше смысла.

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

  1. Это может быть применено только к методам
  2. Вы можете применить его только один раз
  3. Атрибут не может быть унаследован

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

Если вы хотите использовать методы расширения, обновитесь до C# 3.0. В противном случае просто продолжайте вызывать метод, используя синтаксис метода без расширения.

Вы всегда можете взять вызов метода расширения следующим образом:

public static class Utility {
    public static string Extension(this string original) { ... }

// call with:
var newString = myString.Extension();

И позвоните прямо:

string newString = Utility.Extension(myString);

Это будет более соответствовать синтаксису C#/.NET 2 и будет моей рекомендацией.

Другие вопросы по тегам