2011-01-19 3 views
6

Я ищу простые примеры, демонстрирующие, когда полезны ограничения типа типа/ссылочного типа.Когда используется ограничение типа типа/ссылочного типа в C#?

... where T : struct // when is this useful? 
... where T : class // and what about this? 

Я помню, что видел в прошлом несколько хороших примеров, но я просто не могу их найти.

ответ

11

Это позволяет использовать оператор as на T, если он T:class.

Запрещается сравнивать Т с null, если T T:struct.

Обратите внимание, что если вы опустите T:class, вы можете сравнить T с нулем, даже если T - тип значения.

[Примечание: мне нужно было отредактировать это сообщение несколько раз, прежде чем оно получило правильное значение. По крайней мере, я надеюсь, что теперь это правильно.]

-1

«T: class» заставит общий тип, указанный как класс, а не значение. Например, мы можем составить в ObjectList класс, который требует общего типа, указанного быть классом, а не значение:

class ObjectList<T> where T : class { 
    ... 
} 

class SomeObject { ... } 

ObjectList<int> invalidList = new ObjectList<int>(); //compiler error 

ObjectList<SomeObject> someObjectList = new ObjectList<SomeObject>(); //this works 

Это заставляет инвариант на вашем шаблонном типе T, что в противном случае не может быть законной силой. «T: struct» будет работать одинаково. Обратите внимание, что вы также можете использовать эту конструкцию для принудительного применения не только того, что тип T является классом, но также и того, что он соответствует интерфейсу. Образец кода, который я взял, также имеет

class MyList<T> where T : class, IEntity { ... } 
+0

Спасибо , но я знаю семантику общих ограничений - то, о чем я прошу, является примерами, где ограничения struct/class * полезны *. – Oak

1

Основная полезность, которую я нашел в ней, заключается в Marshalling и закреплении объекта в памяти.

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

public static T PinAndCast<T>(this Array o) where T : struct 
{ 
    var handle = System.Runtime.InteropServices.GCHandle.Alloc(o, GCHandleType.Pinned); 
    T result = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); 
    handle.Free(); 
    return result; 
} 
+0

Я думал, что создание новых экземпляров зависит от ограничений «T: new()», а не от ограничений класса/структуры? Кроме того, я не очень хорошо знаком с Marshalling и памятью на C#, не могли бы вы представить пример кода? – Oak

+0

Все зависит от конкретных деталей. В моих случаях мне нужно было преобразовать существующий набор байтов в структуру. Однако создание новых экземпляров, в частности, зависит от ограничения new(). Я отредактировал свой ответ, чтобы отразить это. –

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