Подтвердить что ты не робот

С# Создать новый T()

Вы можете увидеть, что я пытаюсь (но не могу) сделать со следующим кодом:

protected T GetObject()
{
    return new T();
}

Любая помощь будет принята с благодарностью.

EDIT:

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

public class GenericController<T> : Controller
{
    ...

    protected T GetObject()
    {
        return (T)Activator.CreateInstance(ObjectType);
    }        

    public ActionResult Create()
    {
        var obj = GetObject()

        return View(obj);
    }

И поэтому я решил, что размышление здесь было проще всего. Я согласен с тем, что, конечно, с учетом первоначальной постановки вопроса, наиболее подходящим ответом для отметки как правильного является тот, который использует ограничение new(). Я исправил это.

4b9b3361

Ответ 1

Взгляните на новое ограничение

public class MyClass<T> where T : new()
{
    protected T GetObject()
    {
        return new T();
    }
}

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

Вы можете применить одно и то же ограничение к общему методу:

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

Если вам нужно передать параметры:

protected T GetObject(params object[] args)
{
    return (T)Activator.CreateInstance(typeof(T), args);
}

Ответ 3

Другой способ - использовать отражение:

protected T GetObject<T>(Type[] signature, object[] args)
{
    return (T)typeof(T).GetConstructor(signature).Invoke(args);
}

Ответ 4

Просто для завершения, лучшее решение здесь часто требует аргумент функции factory:

T GetObject<T>(Func<T> factory)
{  return factory(); }

и назовите его примерно так:

string s = GetObject(() => "result");

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

Ответ 5

новое ограничение прекрасно, но если вам нужно, чтобы T тоже был типом значений, используйте это:

protected T GetObject() {
    if (typeof(T).IsValueType || typeof(T) == typeof(string)) {
        return default(T);
    } else {
       return (T)Activator.CreateInstance(typeof(T));
    }
}

Ответ 6

Так как это помечено С# 4. С открытой инфраструктурой sourece ImpromptuIntereface он будет использовать dlr для вызова конструктора, это значительно быстрее, чем Activator, когда ваш конструктор имеет аргументы, и пренебрежимо медленнее, когда этого не происходит. Однако главным преимуществом является то, что он будет обрабатывать конструкторы с дополнительными параметрами С# 4.0 правильно, то, что Activator не будет делать.

protected T GetObject(params object[] args)
{
    return (T)Impromptu.InvokeConstructor(typeof(T), args);
}

Ответ 7

Чтобы получить это, я попробовал следующий код:

  protected T GetObject<T>()
    {
        T obj = default(T);
        obj =Activator.CreateInstance<T>();
        return obj ;
    }