2012-04-04 2 views
9
public static class MyClass 
{ 
    public static void Print<T>(this T theObject) 
    { 
     Console.WriteLine("The print output is " + theObject.ToString()); 
    } 
} 

В данном классе я указал общий тип, который можно расширить с помощью ключевого слова this. Поскольку я задерживал определение типа до момента компиляции, как intellisense (и все, что связано с ним) знает, какого типа я продлеваю? C# просто по умолчанию на верхнем уровне System.Object?Что мы расширяем при создании универсального метода расширения?

+2

Что это связано с LINQ? – BoltClock

+0

@ BoltClock'saUnicorn весь беглый sytnax в linq основан на методах расширения. –

+2

@RoyiNamir Тот факт, что LINQ основан на методах расширения, не делает все связанные с LINQ методы расширения. – Servy

ответ

1

Будучи тем, что я отложил определение типа до момента компиляции, как intellisense (и все, что связано с ним) знает, какого типа я расширяю? Действительно ли C# по умолчанию используется для верхнего уровня System.Object?

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

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

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

static class Foo { 
    public static void M(this object obj) { } 
} 

- всего лишь статический метод в статическом классе. Вы могли бы назвать это так:

Foo.M(obj); 

, но мы можем назвать его, как метод экземпляра:

obj.M(); 

Таким образом, если у вас есть общий метод расширения, остановитесь на минуту и ​​думать об этом как статический метод в статическом классе

static class Foo { 
    public static void M<T>(this T obj) { } 
} 

Вы могли бы назвать это так:

object obj; 
Foo.M(obj); 

или вы можете назвать это так:

obj.M(); 

Там нет никакой разницы в компиляторе, который вы пишете.

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

+0

+1 Это полезная информация, которую нужно знать. Как получается, что трюк работает? Предположим ли мы, что это синтаксический сахар? Другими словами, компилятор просто преобразует вызов 'obj.M()' в 'Foo.M (obj)'? –

+1

Да, это просто синтаксический сахар. См. 7.6.5.2 спецификации языка. В частности, в этом разделе делается утверждение «вызов метода затем обрабатывается как вызов статического метода». – jason

+0

@jason 95% info about sytatic sugar и 5% about 'Что мы расширяем? Пожалуйста, поставьте ** доказательство **, что мы не расширяем system.object. –

3

Да, это System.Object, если вы не добавили ограничение типа.

+1

@RoyiNamir: Общие ** параметры ** ('Print ()') могут, а не ограничения ('where T: SomeType'). –

+0

@GeorgeDuckett Я имел в виду, что вам не нужно добавлять тип. T –

+0

Расширение объекта - это не то же самое, что распространяется на все типы, все из которых действительны как параметры типового типа. Это не расширение для объекта. – jason

Смежные вопросы