С# Создать новый 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(). Я исправил это.
Ответы
Ответ 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);
}
Ответ 2
Почему никто не предложил Activator.CreateInstance
?
http://msdn.microsoft.com/en-us/library/wccyzw83.aspx
T obj = (T)Activator.CreateInstance(typeof(T));
Ответ 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 ;
}