Как инициализировать типичный тип параметра T?

Простой вопрос:
Если у вас есть string x, для его инициализации вы просто выполните одно из следующих действий:

string x = String.Empty;  

или

string x = null;

Как насчет универсального параметра T?

Я пробовал:

void someMethod<T>(T y)
{
    T x = new T();  
    ...
}

Сгенерировать ошибку:
Невозможно создать экземпляр типа переменной T, потому что у него нет ограничения new()

Ответ 1

У вас есть два варианта:

Вы можете ограничить T: вы делаете это, добавляя: where T : new() к вашему методу. Теперь вы можете использовать только someMethod с типом, который имеет конструктор по умолчанию без параметров (см. Ограничения по параметрам типа).

Или вы используете default(T). Для ссылочного типа это даст null. Но, например, для целочисленного значения это даст 0 (см. ключевое слово по умолчанию в Generic Code).

Вот базовое консольное приложение, которое демонстрирует разницу:

using System;

namespace Stackoverflow
{
    class Program
    {
        public static T SomeNewMethod<T>()
            where T : new()
        {
            return new T();
        }

        public static T SomeDefaultMethod<T>()
            where T : new()
        {
            return default(T);
        }

        struct MyStruct { }

        class MyClass { }

        static void Main(string[] args)
        {
            RunWithNew();
            RunWithDefault();
        }

        private static void RunWithDefault()
        {
            MyStruct s = SomeDefaultMethod<MyStruct>();
            MyClass c = SomeDefaultMethod<MyClass>();
            int i = SomeDefaultMethod<int>();
            bool b = SomeDefaultMethod<bool>();

            Console.WriteLine("Default");
            Output(s, c, i, b);
        }

        private static void RunWithNew()
        {
            MyStruct s = SomeNewMethod<MyStruct>();
            MyClass c = SomeNewMethod<MyClass>();
            int i = SomeNewMethod<int>();
            bool b = SomeNewMethod<bool>();

            Console.WriteLine("New");
            Output(s, c, i, b);
        }

        private static void Output(MyStruct s, MyClass c, int i, bool b)
        {
            Console.WriteLine("s: " + s);
            Console.WriteLine("c: " + c);
            Console.WriteLine("i: " + i);
            Console.WriteLine("b: " + b);
        }

    }
}

Он производит следующий вывод:

New
s: Stackoverflow.Program+MyStruct
c: Stackoverflow.Program+MyClass
i: 0
b: False
Default
s: Stackoverflow.Program+MyStruct
c:
i: 0
b: False

Ответ 2

используйте ключевое слово default.

T x = default(T);

Смотрите: ключевое слово по умолчанию в общем коде (руководство по программированию на С#)

Учитывая переменную t параметризованного типа T, оператор t = null действует только в том случае, если T является ссылочным типом, а t = 0 будет работать только для числовые значения, но не для структур. Решение состоит в том, чтобы использовать ключевое слово по умолчанию, которое будет возвращать значение null для ссылочных типов и ноль для числовых значений. Для структур будет возвращен каждый член структура, инициализированная нулем или нулем, в зависимости от того, являются ли они значения или ссылочные типы.

Ответ 3

Вам нужно добавить ограничение new для параметра типа T.

void someMethod<T>(T y) where T : new()
{
    T x = new T();  
    ...
}

Это будет действительным только для типов со стандартным конструктором.

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

Ответ 4

Если вам действительно нужен экземпляр T, а не значение по умолчанию для ссылочных типов, используйте:

Activator.CreateInstance()

Ответ 5

Вы можете использовать конструкцию default, чтобы установить ее в значение, заданное типом по умолчанию.

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

Используйте что-то вроде:

T data = default(T);

Подробнее см. в разделе Инициализация общих переменных до их значений по умолчанию