Как расширить класс с помощью методов расширения С#?

Могут ли методы расширения применяться к классу?

Например, добавьте DateTime, чтобы включить метод Tomorrow(), который можно вызвать, например:

DateTime.Tomorrow();

Я знаю, что могу использовать

static DateTime Tomorrow(this Datetime value) { //... }

или

public static MyClass {
  public static Tomorrow() { //... }
}

для аналогичного результата, но как я могу расширить DateTime, чтобы я мог вызывать DateTime.Tomorrow?

Ответ 1

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

Ничего не мешает вам создать свой собственный статический вспомогательный метод, подобный этому:

static class DateTimeHelper
{
    public static DateTime Tomorrow
    {
        get { return DateTime.Now.AddDays(1); }
    }
}

Что вы будете использовать следующим образом:

DateTime tomorrow = DateTimeHelper.Tomorrow;

Ответ 2

Используйте метод расширения.

Пример:

namespace ExtensionMethods
{
    public static class MyExtensionMethods
    {
        public static DateTime Tomorrow(this DateTime date)
        {
            return date.AddDays(1);
        }    
    }
}

Использование:

DateTime.Now.Tomorrow();

или

AnyObjectOfTypeDateTime.Tomorrow();

Ответ 3

Методы расширения - это синтаксический сахар для создания статических методов, первым параметром которого является экземпляр типа T, как если бы он был методом экземпляра на T.

Таким образом, преимущество в значительной степени утрачивается, когда вы делаете "статические методы расширения", поскольку они будут путать читателя с кодом даже больше, чем метод расширения (поскольку они кажутся полностью квалифицированными, но на самом деле не определены в этот класс) без синтаксического усиления (возможность цепочки вызовов в свободном стиле в Linq, например).

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

public static class DateTimeUtils
{
    public static DateTime Tomorrow { get { ... } }
}

И затем используйте это в своем коде через:

WriteLine("{0}", DateTimeUtils.Tomorrow)

Ответ 4

Ближе всего я могу ответить на вопрос, добавив метод расширения в объект System.Type. Не очень, но все же интересно.

public static class Foo
{
    public static void Bar()
    {
        var now = DateTime.Now;
        var tomorrow = typeof(DateTime).Tomorrow();
    }

    public static DateTime Tomorrow(this System.Type type)
    {
        if (type == typeof(DateTime)) {
            return DateTime.Now.AddDays(1);
        } else {
            throw new InvalidOperationException();
        }
    }
}

В противном случае IMO Andrew и ShuggyCoUk имеют лучшую реализацию.

Ответ 5

К сожалению, вы не можете этого сделать. Я считаю, что это было бы полезно. Естественно вводить:

DateTime.Tomorrow

чем:

DateTimeUtil.Tomorrow

С классом Util вы должны проверить наличие статического метода в двух разных классах, а не в одном.

Ответ 6

Я бы сделал то же самое, что и Kumu

namespace ExtensionMethods
{
    public static class MyExtensionMethods
    {
        public static DateTime Tomorrow(this DateTime date)
        {
           return date.AddDays(1);
        }    
    }
}

но назовите его как новый DateTime(). Tomorrow();

Думаю, что он делает больше, чем DateTime.Now.Tomorrow();

Ответ 7

Они предоставляют возможность расширения существующих типов путем добавления новых методов без каких-либо изменений, необходимых для этого типа. Методы вызова из объектов расширенного типа в приложении с использованием синтаксиса метода экземпляра известны как "расширяющие методы". Методы расширения не являются членами экземпляра типа. Ключевым моментом для запоминания является то, что методы расширения, определенные как статические методы, находятся в области видимости только тогда, когда пространство имен явно импортировано в исходный код приложения с помощью директивы using. Несмотря на то, что методы расширения определяются как статические методы, они все еще вызываются с использованием синтаксиса экземпляра.

Посмотрите полный пример здесь http://www.dotnetreaders.com/articles/Extension_methods_in_C-sharp.net,Methods_in_C_-sharp/201

Пример:

class Extension
    {
        static void Main(string[] args)
        {
            string s = "sudhakar";
            Console.WriteLine(s.GetWordCount());
            Console.ReadLine();
        }

    }
    public static class MyMathExtension
    {

        public static int GetWordCount(this System.String mystring)
        {
            return mystring.Length;
        }
    }

Ответ 8

Я искал нечто похожее - список ограничений для классов, которые предоставляют методы расширения. Сложно найти краткий список, вот так:

  • У вас нет никаких личных или защищенных объектов - полей, методов и т.д.

  • Это должен быть статический класс, как в public static class....

  • В классе могут быть только методы, и все они должны быть общедоступными.

  • Вы не можете использовать обычные статические методы - те, которые не включают этот аргумент, не допускаются.

  • Все методы должны начинаться:

    public static ReturnType Имя метода (this ClassName _this,...)

Таким образом, первым аргументом всегда является эта ссылка.

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

Обходной путь заключается в том, чтобы использовать ваш метод расширения как просто фасад для обычного класса, а все статические методы в вашем классе расширения просто называют реальный класс, возможно, используя a Singleton.

Ответ 9

Мы улучшили наш ответ с подробным объяснением. Теперь его легче понять о методе расширения

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

Мы можем расширить наши классы пользовательских классов .net и т.д.

Метод расширения - это особый тип статического метода, который определяется в статическом классе.

Поскольку класс DateTime уже взят выше, и поэтому мы не взяли этот класс для объяснения.

Ниже приведен пример

//Это уже существующий класс калькулятора, который имеет только один метод (Add)

public class Calculator 
{
    public double Add(double num1, double num2)
    {
        return num1 + num2;
    }

}

// Below is the extension class which have one extension method.  
public static class Extension
{
    // It is extension method and it first parameter is a calculator class.It behavior is going to extend. 
    public static double Division(this Calculator cal, double num1,double num2){
       return num1 / num2;
    }   
}

// We have tested the extension method below.        
class Program
{
    static void Main(string[] args)
    {
        Calculator cal = new Calculator();
        double add=cal.Add(10, 10);
        // It is a extension method in Calculator class.
        double add=cal.Division(100, 10)

    }
}