Методы расширения 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, потому что он обеспечивает значимые ограничения для того, как атрибут должен применяться.
- Это может быть применено только к методам
- Вы можете применить его только один раз
- Атрибут не может быть унаследован
Лично я бы рекомендовал избегать всех трех. Каждый вариант делает эту работу, выполняя "трюк" - я бы не стал полагаться на это для производственного кода.
Если вы хотите использовать методы расширения, обновитесь до 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 и будет моей рекомендацией.