Когда ограничение типа / ссылочного типа полезно в C #? - PullRequest
6 голосов
/ 19 января 2011

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

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

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

Ответы [ 3 ]

11 голосов
/ 19 января 2011

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

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

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

[Примечание.По крайней мере, я надеюсь, что теперь это правильно.]

1 голос
/ 19 января 2011

Основная полезность, которую я нашел в этом, заключается в том, что 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 голосов
/ 19 января 2011

"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 { ... }

, что заставляет T быть классом и также быть IEntity.

...