Математика с перечислениями (например, 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", что снова работает.

Другие вопросы по тегам