Использование контрактов кода для создания универсального типа enum - PullRequest
2 голосов
/ 03 января 2012

Несколько дней назад я задал вопрос под названием Как ограничить универсальный тип enum? . Для подведения итогов проблемы используется следующий код:

class MyClass<T> where T : enum // Not possible in C#
{
}

Меня познакомили с контрактными кодами и я смог выдать предупреждение о проблеме во время компиляции, и это все, чего я хочу (чтобы во время компиляции мне сообщали, что T должно быть enum). Я попробовал следующий код ( Полный исходный код ).

class MyClass<T>
{
  public MyClass()
  {
    Contract.Requires(typeof(System.Enum).IsAssignableFrom(typeof(T)));
  }
}

Выдает только бесполезную ошибку во время выполнения. Я должен быть в состоянии выдать предупреждение о времени компиляции, но я не могу заставить его работать. Может кто-нибудь сказать мне, что я делаю не так?

Вот изображение настройки Code Contracts проекта: Code Contracts Setting

1 Ответ

1 голос
/ 03 января 2012

Итак, я написал следующий код в файле:

public class SomeClass<T>
{
    [ContractInvariantMethod]
    private void Invariants()
    {
        Contract.Invariant(typeof(System.Enum).IsAssignableFrom(typeof(T)));
    }

    /// <summary>Initializes a new instance of the SomeClass class.</summary>
    /// <param name="dependency"></param>
    public SomeClass()
    {

    }
}

public class SomeOtherClass
{
    public SomeOtherClass()
    {
        var myClass = new SomeClass<int>();

    }
}

Оттуда я перешел в раздел «Контракты кода» параметров проекта и установил все флажки в разделе «статическая проверка». Затем я переключил уровень предупреждения на «высокий». Когда я перестраивал решение, я получал предупреждение: «Контракты кода: для инварианта требуется недоказанный: typeof (...)», что соответствует инварианту класса.

Оттуда я установил уровень предупреждения на низком уровне и увидел, что предупреждения не было. Поэтому я думаю, что вам нужно установить высокий уровень предупреждения.

Если это не сработает, вы можете попробовать следовать тому, что я сделал, и определить свой контракт как инвариант класса (что, педантично, я бы предложил сделать в любом случае, потому что это скорее концептуально инвариант уровня класса, чем результат выполнения вашего конструктора).

Редактировать: я увидел ваш скриншот после публикации, поэтому я бы изменил его, предложив использовать мое предложение "если это не сработает" с инвариантом уровня класса вместо вызова require из xtor.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...