используя методы расширения на int - PullRequest
14 голосов
/ 12 июля 2011

Я читаю о методах расширения и разбираюсь с ними чтобы посмотреть, как они работают, и я попробовал это:

namespace clunk {
    public static class oog {
        public static int doubleMe(this int x) {
            return 2 * x;
        }
    }

    class Program {
        static void Main() {
            Console.WriteLine(5.doubleMe());
        }
    }
}

и все заработало, как ожидалось, успешно расширив int с помощью метода doubleMe, напечатав 10.

Затем, будучи старым парнем Си, я подумал, смогу ли я сделать это:

namespace clunk {
    public static class BoolLikeC {
        public static bool operator true(this int i)  { return i != 0; }
        public static bool operator false(this int i) { return i == 0; }
    }

    class Program {
        static void Main() {
            if ( 7 ) {
                Console.WriteLine("7 is so true");
            }
        }
    }
}

Я бы подумал, что если первое сработает, то второе должно сработать, чтобы сделать его таким, чтобы int, используемый в логическом контексте, вызовет метод расширения для int, проверьте, чтобы 7 не равно 0 и возвращает true. Но вместо этого компилятору даже не нравится позже код, и помещает красные волнистые линии под этими двумя и говорит "Тип ожидаемый". Почему это не должно работать?

Ответы [ 7 ]

17 голосов
/ 12 июля 2011

Очень умно!Хорошая попытка, но, к сожалению, мы не реализовали «расширение всего» * ​​1002 *, только методы расширения.

Мы рассмотрели реализацию свойств расширения, операторов расширения, событий расширения, конструкторов расширения, интерфейсов расширения, выназвать его, но большинство из них не было достаточно убедительным, чтобы сделать это в C # 4 или в следующей версии C #.Мы дошли до разработки синтаксиса для того типа вещей, которые вы упоминаете.Мы получили намного дальше по свойствам расширения;мы почти получили свойства расширения в C # 4, но в итоге это не сработало.Грустная история здесь.

http://blogs.msdn.com/b/ericlippert/archive/2009/10/05/why-no-extension-properties.aspx

Итак, короче говоря, такой возможности нет, но мы рассмотрим ее для гипотетических будущих выпусков языка.

Конечно, вы можете создать метод расширения "ToBool()" для int, если вам действительно нравится соглашение ретро C, которое non-zero-означает true .

13 голосов
/ 12 июля 2011

Методы расширения - это именно методы.
Вы не можете создавать операторы или свойства расширения.

Если бы это было возможно, это привело бы к очень трудному для чтения коду.
Если выне знакомы с базой кода, почти невозможно понять, что означает if (7).

6 голосов
/ 12 июля 2011

Как уже говорили другие, в C # нет такого понятия, как операторы расширения.

Самое близкое, что вы можете получить, рискуя упростить множество неприятных ошибок в будущем, было бы с неявными операторами преобразования в пользовательском типе "моста":

// this works
BoolLikeC evil = 7;
if (evil) Console.WriteLine("7 is so true");

// and this works too
if ((BoolLikeC)7) Console.WriteLine("7 is so true");

// but this still won't work, thankfully
if (7) Console.WriteLine("7 is so true");

// and neither will this
if ((bool)7) Console.WriteLine("7 is so true");

// ...

public struct BoolLikeC
{
    private readonly int _value;
    public int Value { get { return _value; } }

    public BoolLikeC(int value)
    {
        _value = value;
    }

    public static implicit operator bool(BoolLikeC x)
    {
        return (x.Value != 0);
    }

    public static implicit operator BoolLikeC(int x)
    {
        return new BoolLikeC(x);
    }
}
2 голосов
/ 12 июля 2011

Console.WriteLine(5.doubleMe());

эквивалентно

Console.WriteLine(oog.doubleMe(5));

Учитывая это, вы можете понять, почему if ( 7 ) не работает.

Методы расширения - не более чем синтаксис.

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

2 голосов
/ 12 июля 2011

К сожалению, вы не можете вводить новые операторы или реализовывать поддержку существующих операторов для типов с помощью методов расширения.

По сути, то, что вы хотите сделать, не может быть сделано.

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

Поскольку вы не можете каким-либо образом расширить int, вы не можете это сделать.

1 голос
/ 12 июля 2011

К сожалению, вы не можете использовать методы расширения для добавления операторов, и неявное преобразование типов в C # реализовано как оператор.

0 голосов
/ 12 июля 2011

В первом случае вы пишете метод расширения - например, расширение функциональности типа данных int. Во втором наборе кодов вы пытаетесь переопределить операторы bool. Это две совершенно разные вещи.

...