Существует универсальный конструктор с ограничением параметра в C#?
В C# вы можете поставить ограничение на общий метод, такой как:
public class A {
public static void Method<T> (T a) where T : new() {
//...do something...
}
}
где указано, что T
должен иметь конструктор, который не требует параметров. Мне интересно, есть ли способ добавить ограничение типа"существует конструктор с
6 ответов
Как вы обнаружили, Вы не можете этого сделать.
в качестве обходного пути я обычно предоставляю делегат, который может создавать объекты типа T
:
public class A {
public static void Method<T> (T a, Func<float[,], T> creator) {
//...do something...
}
}
такой конструкции нет. Можно указать только ограничение пустого конструктора.
Я работаю над этой проблемой с лямбда-методами.
public static void Method<T>(Func<int,T> del) {
var t = del(42);
}
Пример Использования
Method(x => new Foo(x));
используя отражение для создания универсального объекта, тип по-прежнему нуждается в правильном объявленном конструкторе или будет выдано исключение. Вы можете передать любой аргумент, если они соответствуют одному из конструкторов.
используется таким образом, вы не можете поставить ограничение на конструктор в шаблоне. Если конструктор отсутствует, исключение необходимо обрабатывать во время выполнения, а не получать ошибку во время компиляции.
// public static object CreateInstance(Type type, params object[] args);
// Example 1
T t = (T)Activator.CreateInstance(typeof(T));
// Example 2
T t = (T)Activator.CreateInstance(typeof(T), arg0, arg1, arg2, ...);
// Example 3
T t = (T)Activator.CreateInstance(typeof(T), (string)arg0, (int)arg1, (bool)arg2);
вот обходной путь для этого, который я лично считаю довольно эффективным. Если вы думаете о том, что такое универсальное параметризованное ограничение конструктора, это действительно сопоставление между типами и конструкторами с определенной сигнатурой. Вы можете создать свое собственное такое сопоставление с помощью словаря. Поместите их в статический класс "фабрика", и вы можете создавать объекты различного типа, не беспокоясь о создании конструктора лямбда каждый раз:
public static class BaseTypeFactory
{
private delegate BaseType BaseTypeConstructor(int pParam1, int pParam2);
private static readonly Dictionary<Type, BaseTypeConstructor>
mTypeConstructors = new Dictionary<Type, BaseTypeConstructor>
{
{ typeof(Object1), (pParam1, pParam2) => new Object1(pParam1, pParam2) },
{ typeof(Object2), (pParam1, pParam2) => new Object2(pParam1, pParam2) },
{ typeof(Object3), (pParam1, pParam2) => new Object3(pParam1, pParam2) }
};
затем в вашем общем метод, например:
public static T BuildBaseType<T>(...)
where T : BaseType
{
...
T myObject = (T)mTypeConstructors[typeof(T)](value1, value2);
...
return myObject;
}
нет. На данный момент единственное ограничение конструктора можно указать для конструктора без аргументов.
Я думаю, что это самое чистое решение, которое ставит ограничение на Способ построения объекта. Это не полностью проверено время компиляции. Когда у вас есть согласие на то, чтобы фактический конструктор классов имел ту же подпись, что и интерфейс IConstructor, это похоже на ограничение на конструктор. The Constructor
метод скрыт при нормальной работе с объектом из-за явной реализации интерфейса.
using System.Runtime.Serialization;
namespace ConsoleApp4
{
class Program
{
static void Main(string[] args)
{
var employeeWorker = new GenericWorker<Employee>();
employeeWorker.DoWork();
}
}
public class GenericWorker<T> where T:IConstructor
{
public void DoWork()
{
T employee = (T)FormatterServices.GetUninitializedObject(typeof(T));
employee.Constructor("John Doe", 105);
}
}
public interface IConstructor
{
void Constructor(string name, int age);
}
public class Employee : IConstructor
{
public string Name { get; private set; }
public int Age { get; private set; }
public Employee(string name, int age)
{
((IConstructor)this).Constructor(name, age);
}
void IConstructor.Constructor(string name, int age)
{
Name = name;
Age = age;
}
}
}