Заставить компилятор жаловаться, если статический порядок вызовов пользовательских функций нарушает некоторые правила - PullRequest
2 голосов
/ 08 апреля 2011

Рассмотрим этот код.

public class Class1
{
    public void ThisShouldNotCompileBecauseOrderWasVoilated()
    {
        Call2();
        Call1();
    }

    public void ThisShouldCompileBecauseProperOrderIsPresent()
    {
        Call1();
        Call2();
    }

    private void Call1()
    {
        // some code
    }

    private void Call2()
    {
        // some more code
    }
}

Какой код (или атрибут) я должен добавить в Call1 () / Call2 (), который гарантирует, что компилятор пожалуется на 1-й метод и передает для 2-го метода.Будет список правил, на который должен ссылаться компилятор, если порядок неправильный.В этом примере список правил может сказать «Call1 Call2», что означает вызов Call1 () перед Call2 ()

Это для языка C # для .NET 4.0

Спасибо!

Ответы [ 4 ]

1 голос
/ 08 апреля 2011

Вы можете создать свой собственный атрибут и пометить свои методы, используя его. Затем создайте правило FXCop. FXCop полностью интегрируется с вашим процессом сборки, и, пока оба вызова выполняются в рамках одного и того же метода, правило должно быть довольно легко реализовано.

1 голос
/ 08 апреля 2011

В обычном C # нет ничего, что вы могли бы указать для этого.

Вы можете иметь возможность использовать что-то вроде NDepend для обнаружения этого, но я не уверен.

0 голосов
/ 08 апреля 2011

Это не совсем то, что вы спрашиваете ... но вы могли бы ввести другой класс:

public class Another1
{
    public Another2 Call1()
    {
        // some code
        return new Another2();  
        // could pass 'this' to Another2 constructor so it has all state
    }
}

public class Another2
{
    public void Call2()
    {
        // some more code
    }
}

Теперь, начиная с экземпляра Another1, вы можете делать только obj.Call1().Call2() и никогда obj.Call2().Call1(). Еще лучше, это принудительное применение в IDE по мере ввода. Взгляните также на «беглые» шаблоны.

0 голосов
/ 08 апреля 2011

компилятор не может принудительно установить порядок вызовов методов, поскольку во многих случаях он не может статически определить порядок вызовов.Например:

public void whichOrder(boolean b)
{
   if (b) call1();
   if (!b) call2();
   if (b) call2();
   if (!b) call1();
}

Если необходимо, чтобы методы вызывались в правильном порядке, у вас есть несколько вариантов:

  • документировать порядок вызовов, чтобы вызывающие абоненты знали, чтосделать.Это не приводит в исполнение порядок, но, по крайней мере, информирует об этом кодеров.
  • добавляет состояние к вашему объекту, чтобы запомнить, какой метод был вызван последним, и проверить, что текущий вызываемый метод разрешен следующим.Это обеспечивает проверку метода во время выполнения.
  • Использование фиктивной инфраструктуры (например, Moq) для модульного тестирования ваших клиентов.Это проверяет во время сборки, что порядок правильный.

Какой подход вы выберете, зависит от того, насколько критичен правильный порядок и последствия вызова методов в неправильном порядке.

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

Например,

public void call3()
{
    call1();
    call2();
}

или

public void call2()
{
   call1();
   // rest of call2's logic
}

private boolean call1Called = false;
pubic void call1()
{
   if (!call1Called)
   {
      call1Called=true;
      call1Impl();
   }

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