Существует ли способ осуществить/ограничить типы, которые передаются примитивам? (bool, интервал, строка, и т.д.)
Теперь, я знаю, что можно ограничить универсальный параметр типа типом или соединить интерфейсом с реализацией через где пункт. Однако это не отвечает всем требованиям для примитивов (AFAIK), потому что у них все нет общего заземления (кроме объекта, прежде чем кто-то скажет! :P).
Так, мои текущие мысли являются только к песку моими зубами и делают большой оператор переключения и бросают ArgumentException на отказ..
РЕДАКТИРОВАНИЕ 1:
Просто для уточнения:
Определение кода должно быть похожим:
public class MyClass ....
И инстанцирование:
MyClass = new MyClass(); // Legal
MyClass = new MyClass(); // Legal
MyClass = new MyClass(); // Illegal
MyClass = new MyClass(); // Illegal (but looks awesome!)
РЕДАКТИРОВАНИЕ 2
@Jon Limjap - Положительная сторона и что-то я уже рассматривал.. Я уверен, что существует общий метод, который может использоваться, чтобы определить, имеет ли тип ценность или ссылочный тип..
Это могло быть полезно в мгновенном удалении большого количества объектов, я не хочу иметь дело с (но затем необходимо волноваться о структурах, которые используются, такие как Размер).. Интересная проблема нет?:)
Вот:
where T : struct
Взятый из MSDN.
Мне любопытно.. Это могло быть сделано в.NET 3.x использование дополнительных методов? Создайте интерфейс и реализуйте интерфейс в дополнительных методах (который, вероятно, был бы более чистым, чем немного толстый переключатель). Плюс то, если затем необходимо позже расшириться на какие-либо легкие пользовательские типы, они могут также реализовать тот же интерфейс без изменений, требуемых к основному коду.
Что делает Вас, парни думают?
Печальные новости, я работаю в Платформе 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 на этом!
Примитивы, кажется, определяются в TypeCode
перечисление:
, Возможно, там путь состоит в том, чтобы узнать, содержит ли объект TypeCode enum
, не имея необходимость бросать его к конкретному объекту или вызову GetType()
или typeof()
?
Обновление Это было правильно под моим носом. Пример кода там показывает это:
static void WriteObjectInfo(object testObject)
{
TypeCode typeCode = Type.GetTypeCode( testObject.GetType() );
switch( typeCode )
{
case TypeCode.Boolean:
Console.WriteLine("Boolean: {0}", testObject);
break;
case TypeCode.Double:
Console.WriteLine("Double: {0}", testObject);
break;
default:
Console.WriteLine("{0}: {1}", typeCode.ToString(), testObject);
break;
}
}
}
Это - все еще ужасный переключатель. Но это - хорошее место для запуска!
В значительной степени, что @Lars, уже сказанный:
//Force T to be a value (primitive) type.
public class Class1<T> where T: struct
//Force T to be a reference type.
public class Class1<T> where T: class
//Force T to be a parameterless constructor.
public class Class1<T> where T: new()
Вся работа в.NET 2, 3 и 3.5.
public class Class1<GenericType> where GenericType : struct
{
}
Этот, казалось, сделал задание..
Если можно терпеть методы фабрики использования (вместо конструкторов MyClass, Вы попросили), Вы могли всегда делать что-то вроде этого:
class MyClass<T>
{
private readonly T _value;
private MyClass(T value) { _value = value; }
public static MyClass<int> FromInt32(int value) { return new MyClass<int>(value); }
public static MyClass<string> FromString(string value) { return new MyClass<string>(value); }
// etc for all the primitive types, or whatever other fixed set of types you are concerned about
}
проблема А здесь состоит в том, что Вам было бы нужно к типу MyClass<AnyTypeItDoesntMatter>.FromInt32
, который является раздражающим. Нет очень хорошего пути вокруг этого, если Вы хотите поддержать частность конструктора, но здесь являетесь несколькими обходными решениями:
MyClass
. Сделайте MyClass<T>
, наследовались от MyClass
и вкладывают его в MyClass
. Переместите статические методы для MyClass
. Это будет вся видимость удаваться, за счет необходимости получить доступ MyClass<T>
как MyClass.MyClass<T>
. MyClass<T>
, как дали. Сделайте статический класс MyClass
, который называет статические методы в [1 111] использование MyClass<AnyTypeItDoesntMatter>
(вероятно, использование соответствующего типа каждый раз, только для хихиканья). MyClass
, который наследовался от [1 114] . (Для конкретности, скажем, MyClass<int>
.), Поскольку можно назвать статические методы определенными в базовом классе через название производного класса, можно теперь использовать MyClass.FromString
. Это дает Вам статическую проверку за счет большего количества записи.
, Если бы Вы довольны динамической проверкой, я использовал бы некоторое изменение на решении TypeCode выше.
Можно упростить EnforcePrimitiveType
метод при помощи typeof(PrimitiveDataType).IsPrimitive
свойство. Я пропускаю что-то?
Используйте пользовательское правило FxCop что использование нежелательного флагов MyClass<>
.
@Rob, Enum
проскользнет через TypeValid
функционируйте, как это TypeCode
Integer
. Я обновил функцию, чтобы также проверить на Enum
.
Private Function TypeValid() As Boolean
Dim g As Type = GetType(T)
Dim code As TypeCode = Type.GetTypeCode(g)
' All of the TypeCode Enumeration refer Primitive Types
' with the exception of Object and Empty (Nothing).
' Note: must also catch Enum as its type is Integer.
Select Case code
Case TypeCode.Object
Return False
Case Else
' Enum's TypeCode is Integer, so check BaseType
If g.BaseType Is GetType(System.Enum) Then
Return False
Else
Return True
End If
End Select
End Function