Поделиться через


Универсальные методы (руководство по программированию на C#)

Универсальный метод — это метод, объявленный с параметрами типа, как показано ниже.

static void Swap<T>(ref T lhs, ref T rhs)
{
    T temp;
    temp = lhs;
    lhs = rhs;
    rhs = temp;
}

В следующем примере кода показан один из способов вызова метода с помощью int аргумента типа:

public static void TestSwap()
{
    int a = 1;
    int b = 2;

    Swap<int>(ref a, ref b);
    System.Console.WriteLine(a + " " + b);
}

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

Swap(ref a, ref b);

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

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

class SampleClass<T>
{
    void Swap(ref T lhs, ref T rhs) { }
}

Если вы определяете универсальный метод, который принимает те же параметры типа, что и содержащий класс, компилятор создает предупреждение CS0693 , так как в области метода аргумент, предоставленный внутренним T , скрывает аргумент, предоставленный для внешнего T. Если требуется гибкость вызова метода универсального класса с аргументами типа, отличными от аргументов типа, предоставленных при создании экземпляра класса, рассмотрите возможность предоставления другого идентификатора параметра типа метода, как показано в GenericList2<T> следующем примере.

class GenericList<T>
{
    // CS0693.
    void SampleMethod<T>() { }
}

class GenericList2<T>
{
    // No warning.
    void SampleMethod<U>() { }
}

Используйте ограничения для включения более специализированных операций с параметрами типа в методах. Эта версия Swap<T>, теперь именованной SwapIfGreater<T>, может использоваться только с аргументами типа, реализующими IComparable<T>.

void SwapIfGreater<T>(ref T lhs, ref T rhs) where T : System.IComparable<T>
{
    T temp;
    if (lhs.CompareTo(rhs) > 0)
    {
        temp = lhs;
        lhs = rhs;
        rhs = temp;
    }
}

Универсальные методы могут быть перегружены по нескольким параметрам типа. Например, следующие методы могут находиться в одном классе:

void DoWork() { }
void DoWork<T>() { }
void DoWork<T, U>() { }

Вы также можете использовать параметр типа в качестве возвращаемого типа метода. В следующем примере кода показан метод, возвращающий массив типа T:

T[] Swap<T>(T a, T b)
{
    return [b, a];
}

Спецификация языка C#

Дополнительные сведения см. в спецификации языка C#.

См. также