Есть ли способ принудительно ввести/ограничить типы, которые передаются примитивам? (bool, int, string и т.д.)
Теперь я знаю, что вы можете ограничить общий тип параметра реализацией типа или интерфейса с помощью предложения where. Однако это не соответствует законопроекту для примитивов (AFAIK), потому что у них не все есть общее основание (кроме объекта, прежде чем кто-то говорит!: P).
Итак, мои текущие мысли состоят в том, чтобы просто скрестить зубы и сделать большой оператор switch и бросить ArgumentException при неудаче.
РЕДАКТИРОВАТЬ 1:
Просто уточнить:
Определение кода должно быть следующим:
public class MyClass<GenericType> ....
И создание экземпляра:
MyClass<bool> = new MyClass<bool>(); // Legal
MyClass<string> = new MyClass<string>(); // Legal
MyClass<DataSet> = new MyClass<DataSet>(); // Illegal
MyClass<RobsFunkyHat> = new MyClass<RobsFunkyHat>(); // Illegal (but looks awesome!)
РЕДАКТИРОВАТЬ 2
@Jon Limjap - Хорошая точка и что-то, что я уже рассматривал. Я уверен, что существует общий метод, который может быть использован для определения того, имеет ли тип значение или ссылочный тип.
Это может быть полезно при мгновенном удалении множества объектов, с которыми я не хочу иметь дело (но тогда вам нужно беспокоиться о структурах, которые используются, например, в Size). Интересная проблема нет?:)
Вот он:
where T : struct
Взято из MSDN.
Мне любопытно.. Это можно сделать в .NET 3.x с использованием методов расширения? Создайте интерфейс и реализуйте интерфейс в методах расширения (который, вероятно, будет более чистым, чем бит-переключатель). Плюс, если вам нужно впоследствии расширить любые легкие пользовательские типы, они также могут реализовать тот же интерфейс, без изменений, необходимых для базового кода.
Что вы, ребята, думаете?
Печальная новость: я работаю в Framework 2!!: D
РЕДАКТИРОВАТЬ 3
Это было так просто, следуя из Jon Limjaps Pointer. Так просто, я почти хочу плакать, но это здорово, потому что код работает как шарм!
Итак, вот что я сделал (вы будете смеяться!):
Код, добавленный в общий класс
bool TypeValid()
{
// Get the TypeCode from the Primitive Type
TypeCode code = Type.GetTypeCode(typeof(PrimitiveDataType));
// All of the TypeCode Enumeration refer Primitive Types
// with the exception of Object and Empty (Null).
// Since I am willing to allow Null Types (at this time)
// all we need to check for is Object!
switch (code)
{
case TypeCode.Object:
return false;
default:
return true;
}
}
Затем небольшой метод полезности для проверки типа и исключения исключений,
private void EnforcePrimitiveType()
{
if (!TypeValid())
throw new InvalidOperationException(
"Unable to Instantiate SimpleMetadata based on the Generic Type of '" + typeof(PrimitiveDataType).Name +
"' - this Class is Designed to Work with Primitive Data Types Only.");
}
Все, что нужно сделать, это вызвать EnforcePrimitiveType() в конструкторах классов. Работа выполнена!: -)
Единственный недостаток, он только генерирует исключение во время выполнения (очевидно), а не время разработки. Но это не имеет большого значения и может быть подобрано с такими утилитами, как FxCop (которые мы не используем на работе).
Особая благодарность Jon Limjap за это!