Математика с перечислениями (например, DayOfWeek) в C # - PullRequest
7 голосов
/ 04 июня 2009

Почему следующий код не будет работать:

endDate.AddDays(7-endDate.DayOfWeek);

Пока это будет:

endDate.AddDays(0-endDate.DayOfWeek + 7);

(Под «не будет работать» я имею в виду следующую ошибку компиляции: «невозможно преобразовать из« System.DayOfWeek »в« double »»)

Ответы [ 3 ]

12 голосов
/ 04 июня 2009

Чтобы расширить то, что сказал Лассе (или, вернее, сделать его немного более явным).

Поскольку 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);
4 голосов
/ 04 июня 2009

Вы можете вычесть два значения перечисления, чтобы получить их разность целочисленных значений:

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», что снова работает.

4 голосов
/ 04 июня 2009

Это очень интересно. Правильный способ сделать это:

endDate.AddDays(7 - (int)endDate.DayOfWeek);

Но ваш вопрос не о решении, а о причине поведения. Это как-то связано с тем, как компилятор обрабатывает ноль. Любая строка не работает, если нет нуля, в то время как обе строки работают, если присутствует ноль.

...