Подтвердить что ты не робот

Есть ли автоматизированный способ уловить самоназвание собственности?

Рассмотрим следующий код:

class C
{
    public int A { get; set; }
    public int B;

    public C(int a, int b)
    {
        this.A = A;    // Oops, bug! Should be `this.A = a`. No warning
        this.B = B;    // Oops, bug! Should be `this.B = b`. `warning CS1717: Assignment made to same variable; did you mean to assign something else?`
    }
}

A и B - почти то же самое, но у меня есть ошибка, которую я пропущу.

Есть ли способ, чтобы я мог поймать первый случай во время компиляции?

EDIT: Некоторые ответы и комментарии хотят объяснить мне, что свойства и поля - это не одно и то же. Я это уже знаю. Они объясняют, почему у компилятора нет предупреждения здесь; Я понимаю. Но я написал ошибку, и мне не нравится писать ошибки. Поэтому мой вопрос: " Как я могу убедиться, что никогда больше не буду писать эту ошибку?"

4b9b3361

Ответ 1

Потенциально вы можете использовать такой инструмент, как FxCop, и написать собственное правило с помощью параметра VisitAssignmentStatement:
Некоторые примеры:
Пример1
Пример2

Ответ 2

Вы сказали, что A = A и B = B одно и то же, но это не так! Вы можете внести изменения в свойства getter и setter, так что A = A может изменить переменную, как в примере ниже:

public Int32 A
{
    get { return _A++; }
    set { _A = value; }
}

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

public UInt32 UniqueID { get { _UniqueID++; } }

public void Reset()
{
    _UniqueID = 0;
}

Заключение

Ошибка времени компиляции здесь не имеет никакого смысла, потому что компилятор не знает, что происходит в свойстве (Помните: свойство - это просто упрощение двух методов, set_MyProperty и get_MyProperty), даже если свойство изменяется (например, путем виртуальное) поведение тоже может измениться.

(РЕДАКТИРОВАТЬ) Избегайте вводящих в заблуждение имен

Я пишу свойства и параметры так же, как вы делаете это. В качестве примера того, как может выглядеть простой класс:

public class MyClass
{
    public Int32 Sample { get; private set; }

    public MyClass(Int32 sample)
    {
        Sample = sample;
    }
}

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

  • Используйте p (arameter) в качестве префикса, однако это то, что я бы не рекомендовал, потому что это делает код нечитаемым IMHO.
  • Используйте value качестве постфикса, для меня это нормально. Таким образом, вместо sample вас будет sampleValue который отличается от Sample (имя свойства), и должно быть легче определить, используется ли имя свойства вместо имени параметра
  • Используйте _ качестве префикса. Я бы не использовал его, потому что я уже использую _ качестве префикса для участников, чтобы обеспечить быстрый доступ к ним, и заставляет intellisense выглядеть странно ИМХО

Я думаю, что это полностью зависит от вашего личного или фирменного стиля кодирования, но я бы лично использовал Value как postfix.

Ответ 3

Это не чугун, но если вы установили ReSharper и установили его проверку для параметра "Неиспользуемый параметр" на "Ошибка" и, кроме того, включили его "Анализ решений", вы увидите это в окне кода:

enter image description here

Один из этих красных индикаторов на правом краю:

enter image description here

И это в строке состояния:

enter image description here

Которые вместе создают комбо, которое в качестве пользователя ReSharper вы скоро не сможете игнорировать:)

Не мешал бы вам компилировать.

Ответ 4

Джей,

Отличный вопрос. Я считаю, что большинство аспектов, которые актуальны, были освещены в различных ответах, но просто для подведения итогов:

  • Невозможно обработать это неявно. Компилятор .Net позволяет рекурсивные свойства, что лежит в основе этой проблемы (с точки зрения невозможности "захватить" ее). Обратите внимание, что в соответствии с этим вопросом это вряд ли изменится.
  • Таким образом, если вы хотите обеспечить захват этой "ошибки", вам нужно будет сделать это явно через сторонний инструмент. Я поклонник ReSharper, как и многие другие, и это позволяет нам в случае необходимости выделять рекурсию свойств. Также, как отмечали другие, использование FXCop вместе с эффективными шаблонами Unit Testing также поможет предотвратить появление таких ошибок.
  • Соглашения об именах - это король. Предоставляя пример, как у вас с преднамеренно "бесполезной" (!) Переменной и именованием свойств, вы точно указали, ПОЧЕМУ мы все должны использовать эффективное соглашение об именах. Проблема, которую вы выделяете, - это тот, который нас всех выгонял и становится все более распространенным по мере роста базы кода.

В то время как потенциально вы не ответили, я думаю, что № 3 является самым важным моментом здесь. Именование элементов должным образом является единственным наиболее эффективным решением. Не только это, но люди могут не иметь роскошь полагаться на ReSharper и другие подобные инструменты.

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

Счастливое кодирование!

Ответ 5

В дополнение ко всем приведенным выше ответам вы также можете в свойствах проекта, в закладке сборки, включить "Обработать предупреждения как ошибки" только с введенными конкретными предупреждениями. Если вы используете компилятор командной строки, используйте:

csc/warnaserror C.cs

csc/warnaserror: 1717 C.cs

Из документации: http://msdn.microsoft.com/en-us/library/406xhdz3.aspx

Это приведет к сбою вашей сборки либо на всех предупреждениях, либо на тех, которые вы указали.

Ответ 6

В порядке:

  • Используйте VB.NET

  • Unit Test ваш код.

  • Используйте ReSharper и принимайте приглашение "Qualifer 'this' является избыточным" - затем найдите предупреждения: Assignment made to same variable; did you mean to assign something else?

  • Я увидел предложение FxCop и подумал "Правила анализа пользовательского кода" с использованием Introspection.

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

Многие разработчики С# объявляют переменную так же, как имя типа, кроме первой буквы в нижнем регистре. Эта практика может быть чем-то, что вы хотите изменить.

Ответ 7

Почему самосознание поля this.B = B; неверно? Потому что ничего не делает. this.B и B - это то же самое.

Почему самоопределение свойства this.A = A; не так? Поскольку значение A зависит от того, на какой стороне оператора = он стоит. Посмотрите, как компилятор видит этот код:

set_A(get_A());

Это вызов двух разных методов. Как вы думаете, это предупреждение, если вы назовете Foo(Bar());? Также не компилятор. Нехорошо менять хранилище резервных копий в getter, но рассмотрите свойство, в котором вы подсчитываете количество показаний или делаете некоторые записи, или ставите любую другую логику. Почему компилятор предупредил вас об этом?

public int A
{
    get 
    {
       _log.Debug("Property A accessed by some user");
       _readingsCount++;
       // your logic goes here
       return _a;
    }    
}