Есть ли снижение производительности при создании методов расширения, которые работают с типом «объект»? - PullRequest
27 голосов
/ 04 октября 2011

У меня есть набор методов расширения, которые я регулярно использую для различных задач пользовательского интерфейса. Обычно я определяю их для запуска типа object, хотя внутри них я обычно конвертирую их в строковые типы.

public static string FormatSomething(this object o)
{
     if( o != null )
     {
          string s = o.ToString();
          /// do the work and return something.
     }
     // return something else or empty string.

}

Основная причина, по которой я использую тип object, а не string, заключается в том, чтобы уберечь себя в пользовательском интерфейсе от необходимости делать <%#Eval("Phone").ToString().FormatSomething()%>, когда я могу вместо него ввести <%#Eval("Phone").FormatSomething()%>.

Итак, нормально ли с точки зрения производительности создавать все методы расширения для object, или я должен преобразовать их в string (или соответствующие) типы, основываясь на том, что делает метод расширения?

Ответы [ 4 ]

54 голосов
/ 04 октября 2011

Есть ли снижение производительности при создании методов расширения, работающих с типом объекта?

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

Вместо

public static string FormatSomething(this object o) 
{
    return (o != null) ? o.ToString() : "";
}

я бы написал

public static string FormatSomething<T>(this T o) 
{
    return (o != null) ? o.ToString() : "";
}

Это имеет тот же эффект, но позволяет избежать штрафа за бокс.Или, скорее, он торгует за звонок штраф за бокс для первого звонка штраф за джитинг.

это нормально с точки зрения производительности, чтобы создать все расширениеметоды на объекте?

Мы не можем ответить на вопрос.Попытайся!Измерьте производительность, сравните ее с желаемой производительностью и посмотрите, достигли ли вы своей цели.Если вы сделали, отлично.Если нет, воспользуйтесь профилировщиком, найдите самую медленную вещь и исправьте ее.

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

Это хорошая практика программирования для создания метода расширения, который расширяет все?

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

Например, предположим, что вы хотите иметь метод расширения, который отвечает на вопрос "эта последовательность содержит это значение? "Вы можете написать:

public static bool IsContainedIn<T>(this T item, IEnumerable<T> sequence)

и затем сказать

if (myInt.IsContainedIn(myIntSequence))

Но гораздо лучше сказать:

public static bool Contains<T>(this IEnumerable<T> sequence, T item)

, а затем сказать

if (myIntSequence.Contains(myInt))

Если вы делаете это первым способом, тогда вы печатаете в IDE и каждый раз, когда вы набираете «.», Вам предлагается ввести IsContainedIn в качестве опции, потому что возможно you 'собирается написать код, который определяет, находится ли этот объект в коллекции.Но в 99% случаев вы этого не сделаете.Это добавляет шум в инструмент и затрудняет поиск того, что вы действительно хотите.

2 голосов
/ 04 октября 2011

По сравнению с тем, когда вы вызываете ToString, потому что вызов функции FormatSomething не совсем (проверка нуля может занять несколько мс, но они также делают код более устойчивым.

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

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

2 голосов
/ 04 октября 2011

Я серьезно сомневаюсь, что это может повлиять на производительность, возможно, даже за счет влияния IDE. После компиляции я не ожидал, что это что-то изменит.

1 голос
/ 04 октября 2011

Какие издержки связаны с методом расширения во время выполнения?(.NET) отвечает на ваш вопрос, я думаю.Методы расширения являются просто статическими методами, поэтому они не относятся к типу Object.Intellisense только заставляет это казаться.

...