Универсальная проверка типа

Существует ли способ осуществить/ограничить типы, которые передаются примитивам? (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 на этом!

71
задан Community 23 May 2017 в 12:02
поделиться

7 ответов

Примитивы, кажется, определяются в 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;
        }
    }
}

Это - все еще ужасный переключатель. Но это - хорошее место для запуска!

39
ответ дан Apurv 24 November 2019 в 12:59
поделиться

В значительной степени, что @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.

22
ответ дан Peter Mortensen 24 November 2019 в 12:59
поделиться
public class Class1<GenericType> where GenericType : struct
{
}

Этот, казалось, сделал задание..

74
ответ дан Lars Mæhlum 24 November 2019 в 12:59
поделиться

Если можно терпеть методы фабрики использования (вместо конструкторов 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 выше.

4
ответ дан Doug McClean 24 November 2019 в 12:59
поделиться

Можно упростить EnforcePrimitiveType метод при помощи typeof(PrimitiveDataType).IsPrimitive свойство. Я пропускаю что-то?

2
ответ дан Vivek 24 November 2019 в 12:59
поделиться

Используйте пользовательское правило FxCop что использование нежелательного флагов MyClass<>.

2
ответ дан Peter Mortensen 24 November 2019 в 12:59
поделиться

@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
3
ответ дан Matthew Boehlig 24 November 2019 в 12:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: