Есть ли способ отключить неявные приведения из UInt32 в char? - PullRequest
7 голосов
/ 06 января 2012

Я работаю над кодом, который принимает в качестве входных данных тонну текста ascii, определенного конкретным протоколом. Первоначальный автор интерпретировал типы данных "string (1)" в исходном протоколе как символы в коде.

В угловых случаях, где у вас есть такой код, было много тонких ошибок:

char theChar = whatever();
if(theChar == 7) {...} 

где на самом деле подразумевалось:

if(theChar == '7') {...}

Чтобы попытаться поймать все сразу, есть ли способ отключить неявное приведение к 'char'? Если нет, то как лучше всего отследить все это?

Ответы [ 4 ]

4 голосов
/ 06 января 2012

Вы должны быть в состоянии написать тривиальный класс замены для char (который содержит char в качестве данных и предоставляет несколько операторов приведения, позволяющих использовать его, как если бы он был char), который не допускает неявных приведений to / from ints, а затем выполните поиск и замените 'char' на 'mychar'. Это приведет к ошибкам компилятора, которые вы можете исправить, а затем, если вы захотите, вы можете снова использовать код для использования char или придерживаться своего класса.

Это хороший пример места, где временное использование макросов так полезно в c ++ ...

2 голосов
/ 06 января 2012

Мое предложение найти существующие ошибки, такие как описанная, состоит в том, чтобы использовать Visual Studio для выполнения поиска по всему решению (Ctrl + Shift + F) с использованием регулярных выражений.

  • Нажмите Ctrl + Shift + F
  • Выберите «Использовать: регулярные выражения» в разделе «Параметры поиска»
  • Введите следующее регулярное выражение в поле «Найти что»: [^ 0-9a-zA-Z _] [0-9] + [^ 0-9]

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

Вы можете дополнительно сузить результаты поиска, сосредоточившись на конкретном типе проблемы. Например, чтобы найти код в представленном примере, вы можете настроить следующее выражение: == (| \ t | \ r | \ n) * [0-9] + [^ 0-9]


Оригинальный ответ

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

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

static class MenuSelection
{
    public const char Open = '1';
    public const char Edit = '2';
    public const char Save = '3';
    // ...
    public const char Close = '7';
}

И тогда MenuSelection следует использовать в операторе if, как показано ниже:

char theChar = whatever();
if(theChar == MenuSelection.Close) {...} 

Это на самом деле не решает проблему неявного преобразования из UInt32 в char, но, надеюсь, человек, пишущий код для констант в классе MenuSelection, с меньшей вероятностью забудет кавычки.

РЕДАКТИРОВАТЬ: О, после того, как он попробовал, кажется, что это как-то решает проблему неявного преобразования, потому что public const char Close = 7; вызывает ошибку компиляции.

К сожалению, это не поможет вашей насущной проблеме: много существующего кода, содержащего такие ошибки.

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

Как решение «однажды исправить», я думаю, что решение FxCop Джеймса Майкла Хейра самое простое.

Чтобы в будущем не возникало проблем с рефакторингом, используйте нестандартный тип данных вместо char, чтобы вы могли определить точные операции, которые вам нужны, может быть хорошей идеей.

0 голосов
/ 06 января 2012

Нет, поведение, разрешающее выражение theChar == 7, является частью спецификации C # и не может быть изменено.

Обратите внимание, что фактическое неявное преобразование здесь - из char в int, а не из int в char.

Вот как это работает:

  • Литерал 7 имеет тип int.
  • Переменная theChar имеет тип char.
  • Чтобы применить оператор == к двум выражениям, компилятор должен выбрать оператор ==.
    • Нет оператора ==, который принимает char в качестве первого аргумента и int в качестве второго.
    • Нет неявного преобразования из int в char (поскольку такое преобразование может привести к потере информации).
    • Там - это неявное преобразование из char в int.
    • Компилятор преобразует выражение char в int и использует оператор ==, который принимает два ints.
...