Методы расширения и класс статической полезности

Я ищу некоторые плюсы и минусы для использования методов расширения поверх статических классов утилиты в приложении С#.

Например, плюсом в столбце методов расширения является удобство вызова по имени класса, а не нечто вроде "StringUtils". Но конфликт был бы в том, что он может размыть линии между тем, что находится в рамках, а что нет.

Ответ 1

Я бы сказал, что pro - это то, что он размывает линии между тем, что находится в рамках, а что нет: вы можете использовать свой собственный код так же естественно, как и код рамки, работающий на типах фреймов.

Методы расширения не должны использоваться произвольно, конечно - это не похоже на то, что все статические методы должны стать методами расширения.

Я пытаюсь думать о нем, как метод логически управляет "on" его первым параметром. Будет ли это иметь смысл как метод экземпляра, если бы вы могли включить его в качестве метода экземпляра?

A "con", о котором вы не можете знать: если позднее расширенный тип добавляет метод экземпляра того же имени, который применим к тем же параметрам, ваш код вызова будет прозрачно запускать этот метод экземпляра в следующий раз, когда вы перекомпилируете, Например, Stream получил CopyTo в .NET 4... Ранее я написал метод расширения CopyTo, который затем не будет называться. Там нет предупреждения, что это происходит, поэтому вы должны быть настороже.

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

Ответ 2

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

string foo = "bob";
StringUtils.DoSomething(foo);

и

string foo = "bob";
foo.DoSomething();

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

Наконец, методы расширения можно также вызвать как статические методы!

string foo = "bob";
StringExtensions.DoSomething(foo);

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

Ответ 3

Мне лично нравятся readabilty и chain calls (неявно обеспечивает читаемость), предоставляемые методами расширения.

 1) Readability:  
     bool empty = String.IsNullOrEmpty (myString)
     //in comparison to
     bool empty = myString.IsNullOrEmpty ();

 2) Chain calls:  
    var query = Enumerable.Range(0, 10)
                         .Where(x => x % 2 == 0)
                         .Reverse();
    //instead of
    var query = Enumerable.Reverse(Enumerable.Where(Enumerable.Range(0, 10), x => x % 2 == 0));

Con - ваш метод расширения может быть переопределен членом-членом, если вы случайно это сделаете. Лично мне это не нравится. По крайней мере, компилятор должен был кричать, если это происходит в той же сборке.