Математика с перечислениями (например, DayOfWeek) в C#
Почему следующий код не будет работать:
endDate.AddDays(7-endDate.DayOfWeek);
Пока это будет:
endDate.AddDays(0-endDate.DayOfWeek + 7);
?
(Под "не будет работать" я имею в виду следующую ошибку компиляции: "невозможно преобразовать из" System.DayOfWeek "в" double "")
3 ответа
Чтобы расширить то, что сказал Лассе (или, вернее, сделать это немного более явным).
Поскольку 0 преобразуем в тип Enum,
0 - endDate.DayOfWeek becomes
(DayOfWeek)0 - endDate.DayOfWeek
А так как вы можете вычесть одно перечисление из другого и получить целочисленную разницу:
(DayOfWeek)0 - endDate.DayOfWeek == (int)endDate.DayOfWeek
Таким образом, поскольку результатом вычитания является int, вы можете добавить 7 к нему.
endDate.AddDays(0-endDate.DayOfWeek + 7);
Итак, если значение Enum понедельника равно 1
0 - endDate.DayOfWeek == -1 + 7 == 6
Тем не менее, вы не можете сделать обратное.
endDate.DayOfWeek - 0 + 7,
потому что тип результата расчета зависит от самой левой стороны. Таким образом, в то время как 0 - endDate.DayOfWeek приводит к целому числу, endDate.DayOfWeek - 0 приводит к перечислению DayOfWeek.
Самое интересное, что вы могли бы использовать этот побочный эффект, чтобы получить значение enum без приведения, хотя я бы посчитал это хакерским и запутанным... поэтому его следует избегать.
int enumValue = -(0 - endDate.DayOfWeek);
Это очень интересно. Правильный способ сделать это:
endDate.AddDays(7 - (int)endDate.DayOfWeek);
Но ваш вопрос не о решении, а о причине поведения. Это как-то связано с тем, как компилятор обрабатывает ноль. Любая строка не работает, если нет нуля, в то время как обе линии работают, если присутствует ноль.
Вы можете вычесть два перечислимых значения, чтобы получить их разность целочисленных значений:
using System;
namespace ConsoleApplication10
{
public enum X { A, B, C, D }
public class Program
{
static void Main()
{
var x = X.D + X.A;
Console.Out.WriteLine(x);
Console.In.ReadLine();
}
}
}
Распечатает 3.
Но вы не можете добавить, вероятно, не имеет смысла.
В случае "0" 0 автоматически преобразуется во все типы enum, поэтому в основном "0 - enumvalue" означает то же самое, что и "(enumtype)0 - enumvalue", что снова работает.