Як визначити обмеження загального типу для примітивних типів?


81

У мене є такий метод із загальним типом:

T GetValue<T>();

Я хотів би обмежити T до примітивних типів, таких як int, string, float, але не класу. Я знаю, що можу визначити загальний для типу класу так:

C GetObject<C>() where C: class;

Я не впевнений, чи можливо це для примітивних типів і як, якщо так.


Я думаю, що під "примітивними типами" @ David.Chu.ca означає "некеровані типи", тобто int, floatтощо, не Int32, Int64і Singleт. Д. Хоча classпозначає тип ref, "але не тип класу" передбачає різницю між некерованими та керованими примітивами.
mireazma

Відповіді:


50

Ви можете використовувати це, щоб обмежити його типом значень:

where C: struct

Ви також згадуєте рядок. На жаль, рядки заборонені, оскільки вони не є типами значень.


2
але не для рядка, який є
недійсним

5
І, звичайно, це дозволяє передавати будь-який визначений користувачем тип структури, а не лише примітивні типи. Я не впевнений, що існує спосіб, крім визначення перевантажень для всіх вбудованих примітивних типів.
Метт Гамільтон,

1
Питання було до примітивів, а не до типів цінностей. Як ви зазначаєте у своїй відповіді, примітивний рядок не є типом значення, тому він не працює в цьому відношенні - також він дозволить вам передавати випадкові структури (як зазначає @MattHamilton), які не є примітивними.
BrainSlugs83,

1
З цим, якщо у мене є метод, який робить, n1 + n2де n1 та n2 мають обидва типи C, це Operator '+' cannot be applied to operands of type 'C' and 'C'
видає

25

Насправді це робить роботу певною мірою:

public T Object<T>() where T :
   struct, IComparable, IFormattable, IConvertible, IComparable<T>, IEquatable<T>

Щоб обмежити числові типи, ви можете отримати кілька корисних підказок щодо наступних зразків, визначених для класу ValueType


Примітка: якщо ви використовуєте це для подачі поля ідентифікатора до бази даних, так само, як і я, структура Guid не підтримує IConvertibleінтерфейс, і ви можете видалити його.
deadManN

15

Ось що ви шукаєте:

T GetObject<T>() where T : struct;

Боже! Я ненавиджу, коли мене хтось б'є до кінця. Приємного BFree!
Джошуа Белден

1
як щодо рядка, який є примітивним, але
дозвільним

4
@David: рядок не є примітивним типом. Це посилальний тип, який в деяких випадках трактується як примітивний тип.
Самуель

Але немає можливості закинути динамічно отримані об'єкти, щоб задовольнити цю structвимогу, чи не так?
Nyerguds,

1
Рядок - примітивний, але не тип структури / значення.
BrainSlugs83,

11

Не існує загального обмеження, яке б точно відповідало цій сукупності речей. Що ви насправді хочете зробити? Наприклад, ви можете зламати його за допомогою перевірок виконання, таких як статичний ctor (для загальних типів - не так просто для загальних методів) ...

Однак; Найчастіше я бачу це, тому що люди хочуть одне з:

  • щоб мати можливість перевіряти предмети на рівність: у цьому випадку використовуйте EqualityComparer<T>.Default
  • щоб мати можливість порівнювати / сортувати предмети: у цьому випадку використовуйте Comparer<T>.Default
  • щоб мати можливість виконувати арифметику: у цьому випадку використовуйте підтримку MiscUtil для загальних операторів


7

Що ви насправді намагаєтесь зробити у методі? Можливо, вам насправді потрібен C для реалізації IComparable або якийсь інший інтерфейс. У такому випадку ви хочете щось подібне

T GetObject<T> where T: IComparable
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.