Является ли оператор + = b из char таким же, как a = a + b?
Нашел интересную проблему: следующий код работает с другим результатом:
char c = 'a';
c += 'a'; //passed
c = c + 'a'; //Cannot implicitly convert type 'int' to 'char'. An explicit conversion exists (are you missing a cast?)
Есть ли разница между a += b
и a=a+b
, или просто проверка кода компилятора пропустила его?
Моя точка зрения, почему char += char
может передавать проверку кода, а char = (char+char)
считается char = int
?
Ответы
Ответ 1
Спецификация С#, раздел 7.17.2 Составное назначение:
Операция формы x op= y
обрабатывается путем применения разрешения перегрузки бинарных операторов (§7.3.4), как если бы операция была написана x op y
. Тогда,
...
• В противном случае, если выбранный оператор является предопределенным оператором, если тип возврата выбранного оператора явно конвертируется в тип x
, а если y
неявно конвертируется в тип x
или оператор является оператором сдвига, тогда операция оценивается как x = (T)(x op y)
, где T
является типом x
, за исключением того, что x
оценивается только один раз
И это именно то, что мы имеем здесь. Тип возврата операции int
, но типы x
и y
являются char
, и поэтому для нас автоматически добавляется дополнительный листинг.
(Я считаю, что это правило существует, потому что вам нигде не нужно вставлять явное выделение, и это вроде как "ожидается", особенно в тех случаях, когда x
и y
являются одним и тем же типом)
Ответ 2
Во втором случае это присваивание, которое не выполняется, а не само вычисление. Если вы явно передали результат во второй строке в char, он отлично работает, и, действительно, следующие три строки генерируют идентичный IL:
c += (char)1;
c = (char)(c + (char)1);
c = (char)(c + 1);
Так что да. Есть разница.
Обратите внимание, что в третьей строке я не стал набрасывать 1
на char
, так как вычисление просто преобразует его обратно в int.
Ответ 3
Результирующий тип + = is char в этом случае, и результирующий тип c + (char) 1 является int.
Следующий код печатает:
o1 System.Char o2 System.Int32
public static void Main(string[] args)
{
char c = 'a';
object o1 = c += (char)1;
object o2 = c + (char)1;
WriteLine("o1 " + o1.GetType());
WriteLine("o2 " + o2.GetType());
}
Ответ 4
Чтобы дать ответ Damien в более простых выражениях:
Составные операторы (например, +=
, -=
и т.д.) автоматически приводят результат к целевому типу (если это возможно).
Поэтому c += 'a'
работает, потому что он оценивается как c = (char)(c + 'a')
.
В этом случае преобразование необходимо, поскольку возвращаемый тип арифметических операций между символами равен int
(поэтому c = c + 'a'
не компилируется, так как ему не хватает приведенного выше).