Методы расширения в С# - Это правильно?

Я недавно вникал в С#, и я задаюсь вопросом, не будет ли кто-нибудь просто проверять мою запись на нем, чтобы убедиться, что это точно?

Пример: вычисление факториалов с использованием метода расширения.

Например, если вы хотите расширить тип int, вы можете создать класс, например. NumberFactorial и создать способ, например. Static Void Main, который вызывает, например, int x = 3 Затем печатает строку (после ее возврата из метода расширения)

Создать открытый статический метод, содержащий ключевое слово "this", например. это int x выполнить логику, а затем параметр возвращается к встроенному методу вывода.

Код ниже:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            int x = 3;
            Console.WriteLine(x.factorial());
            Console.ReadLine();
        }
    }
    public static class MyMathExtension
    {
        public static int factorial(this int x)
        {
            if (x <= 1) return 1;
            if (x == 2) return 2;
            else
                return x * factorial(x - 1);
        }
    }
}

Ответ 1

Да, это правильно.

Методы расширения определяются как статические методы, но вызываются с помощью синтаксиса метода экземпляра. Их первый параметр указывает, на какой тип работает метод, и этому параметру предшествует этот модификатор. Методы расширения доступны только в том случае, если вы явно импортируете пространство имен в исходный код с помощью директивы using.

Вы можете узнать больше о методах расширения здесь и здесь

Ответ 2

Это, безусловно, выглядит точным. Тем не менее, мне интересно, почему вы хотели бы иметь два условия выхода, когда только один действительно нужен. Кроме того, если вы сделали код, вы легко сможете unit test его удостовериться, что он точным.

Ответ 3

Выглядит хорошо. Кстати, вы могли бы также сделать

public static class MyMathExtension
{
    public static int factorial(this int x)
    {
        if (x <= 1)
            return 1;
        else
            return x * (x - 1).factorial();
    }
}

Ответ 4

То, как я рассматриваю методы расширения, - это способность обнаруживать и универсальность.

Для таргетинга на встроенный тип .NET я делаю серьезные соображения по поводу намерения приложения. Используя ваш пример факториала, я бы спросил себя

Как часто мне нужно myint.Factorial()?

Ответ на этот вопрос для большинства доменов будет, не так много. Имея это в виду, если мне действительно нужно реализовать myint.Factorial(), в этот момент я возьму класс, который у вас есть MyMathExtension, и сделайте это частным классом внутри класса, который действительно будет использовать метод Factorial. На данный момент это становится еще одним внутренним, частным вспомогательным методом (я хочу, чтобы .NET разрешило нам объявлять это встроенным классом вместо принудительного создания класса оболочки без каких-либо причин)

Теперь, если ваш домен был математическим приложением, которое по какой-либо причине использует вычисление факториалов широко, настолько, что вы хотите, чтобы сам тип int реализовал факториал.

В этот момент я бы создал метод в

namespace System {
    public class IntExtension {
        public int Factorial(this int....) 
    }
}

Это специально нарушает рекомендации Microsoft по использованию метода расширения. Корпорация Майкрософт рекомендует не использовать пространство имен this Owner obj из-за того, что пространство имен находится за пределами вашего домена. Если я правильно помню, их основное обоснование этой причины заключается в том, что это пространство имен вне вашего домена, оно подвержено мутации. Я по существу не согласен с тем, что Microsoft не хочет, чтобы это было сделано. Мое заключение заключается в том, что на сборке произойдут изменения, которые будут затронуты использованием пространства имен, которые у вас были бы связаны с нарушением изменений и должны были бы перенаправлять миграцию независимо от того, и теперь самое подходящее время для внутреннего использования внутреннего пространства имен.

Я считаю, что лучше всего использовать ваши общедоступные методы расширения для пространства имен принадлежащего вам типа. Это для всех интенсивных целей делает ваш класс метода расширения более похожим на строки на частичный класс того же типа. Это возвращает мою первоначальную формулировку методов расширенного просмотра в отношении обнаружения. Использование одного и того же пространства имен делает ваше расширение более понятным особенно, если вы не программируете такие инструменты, как Resharper.

Ответ 5

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