2012-01-20 1 views
4

Можно создать дубликат:
What does this C# syntax mean?Использование 'где' в C#

Может кто-то просьба разъяснить мне разницу между следующими декларациями класса в C#:

public class SomeClass<T> where T : ISomeInterface 

по сравнению с

public class SomeClass<ISomeInterface> 
+3

возможно дубликат [Что это C# синтаксис в виду?] (Http://stackoverflow.com/questions/2739859/what-does-this-c-sharp-syntax-mean), [C#, где ключевое слово ] (http://stackoverflow.com/questions/2774041/c-sharp-where-keyword) –

+0

@CodyGray Вы проголосовали за закрытие этой второй ссылки в своем комментарии. Вы действительно должны иметь заинтересованность в ограничениях 'Where' или общих типах. –

+0

@Chase: Я просто сделал, да, потому что это дубликат другого вопроса, который я нашел. Я заинтересован в уменьшении избыточности и дублирования. Это облегчает поиск ответов, которые вы ищете. –

ответ

8

Первый ограничивает T в классе, который является типом, который является производным или реализует данный интерфейс.

Если у вас есть

class Foo : ISomeInterface { } 
class Bar : ISomeInterface { } 
class Baz { } 

С первым определением, вы бы тогда быть в состоянии построить общий экземпляр с первыми двумя типами, а не третьим.

public class SomeClass<T> where T : ISomeInterface // your definition 

var obj1 = new SomeClass<Foo>(); 
var obj2 = new SomeClass<Bar>(); 
var obj3 = new SomeClass<Baz>(); // not legal, Baz does not implement ISomeInterface 

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

public class SomeClass<ISomeInterface> // your definition 

var obj1 = new SomeClass<Foo>(); 
var obj2 = new SomeClass<Bar>(); 
var obj3 = new SomeClass<Baz>(); // legal, there is no constraint 

Edit: Из комментариев ниже

Я тест "var obj3 = new SomeClass<Baz>();", и это работает, но я не понимаю, почему. Я думаю, что не понимаю этого утверждения: «Во-вторых, все, что вы сделали, - это объявить параметр типа, который имеет то же имя, что и интерфейс».

Когда вы объявляете общее определение класса public class Blah<T>, то T является заполнителем. Это параметр типа, который будет заполнен позже. В вашей второй версии public class SomeClass<ISomeInterface>, ISomeInterface - это имя заполнителя! Он не является интерфейсом, он не ограничивает класс использованием ISomeInterface, он просто использует то же имя, что и имя параметра типа. Аргумент типа может быть любым. Это аргумент , который заполняет местозаполнитель. var foo = new SomeClass<string>(). Здесь общий параметр был заполнен string.

Вы заполняете в аргументе, делая то, что я делал раньше, просто создавая экземпляр

var instance = new SomeClass<string>(); 

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

class AppleSomeClass : SomeClass<Apple> 

Дело в том, что это конвенции использовать T в одной ситуации типа параметра, но это только конвенции. T вместо этого можно назвать что угодно. У. X. Яблоко. Вы обнаружили, что вы также можете назвать его тем же, что и существующий тип, что, к сожалению, привело к вашей путанице здесь.


Оригинальный ответ продолжал

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

where T : class // reference type 
where T : struct // value type 

Вы можете указать, что он должен быть унаследован от класса или реализовать интерфейс

where T : Foo // derives from Foo 
where T : IFoo // implements IFoo 

И вы можете потребовать, чтобы он имеет конструктор без параметров

where T : new() 

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

where T : class, IFoo 
where T : class, new() 
where T : class, Foo, new() 
+0

Благодарим вас за подробное объяснение. Я тестировал «var obj3 = new SomeClass ();» и это работает, но я не понимаю, почему. Я думаю, что не понимаю этого утверждения: «Во-вторых, все, что вы сделали, - это объявить параметр типа, который имеет то же имя, что и интерфейс». – Sandy

+0

@ Сэнди, см. Расширение ответа. –

+0

Получил это. Большое спасибо Энтони. – Sandy

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