C #에 매개 변수 제약 조건이있는 일반 생성자가 있습니까?
C #에서는 다음과 같은 일반적인 방법에 제약 조건을 둘 수 있습니다.
public class A {
public static void Method<T> (T a) where T : new() {
//...do something...
}
}
지정하는 T
경우 매개 변수가 필요없는 생성자가 있어야합니다. " 매개 변수 가있는 생성자가 float[,]
있습니까? " 와 같은 제약 조건을 추가 할 수있는 방법이 있는지 궁금합니다.
다음 코드는 컴파일되지 않습니다 :
public class A {
public static void Method<T> (T a) where T : new(float[,] u) {
//...do something...
}
}
해결 방법도 유용합니까?
알다시피, 당신은 이것을 할 수 없습니다.
해결 방법으로 나는 보통 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);
개인적으로 매우 효과적이라고 생각하는 해결 방법은 다음과 같습니다. 일반 매개 변수화 된 생성자 제약 조건이 무엇인지 생각하면 실제로는 특정 서명을 가진 형식과 생성자 간의 매핑입니다. 사전을 사용하여 고유 한 매핑을 만들 수 있습니다. 이것을 정적 "factory"클래스에 넣으면 매번 생성자 람다를 구축하지 않아도 다양한 유형의 객체를 만들 수 있습니다.
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) }
};
then in your generic method, for example:
public static T BuildBaseType<T>(...)
where T : BaseType
{
...
T myObject = (T)mTypeConstructors[typeof(T)](value1, value2);
...
return myObject;
}
No. At the moment the only constructor constraint you can specify is for a no-arg constructor.
I think this is the most clean solution that kind of puts a constraint on the way an object is constructed. It is not entirely compile time checked. When you have the agreement to make the actual constructor of the classes have the same signature like the IConstructor interface, it is kind of like having a constraint on the constructor. The Constructor
method is hidden when working normally with the object, because of the explicit interface implementation.
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;
}
}
}
How about creating your generic class with constraints, here I chose struct and class to have value and reference types.
That way your constructor has a constraint on the values.
class MyGenericClass<T, X> where T :struct where X: class { private T genericMemberVariableT; private X genericMemberVariableX; public MyGenericClass(T valueT, X valueX) { genericMemberVariableT = valueT; genericMemberVariableX = valueX; } public T genericMethod(T genericParameter) { Console.WriteLine("Parameter type: {0}, value: {1}", typeof(T).ToString(), genericParameter); Console.WriteLine("Return type: {0}, value: {1}", typeof(T).ToString(), genericMemberVariableT); Console.WriteLine("Return type: {0}, value: {1}", typeof(X).ToString(), genericMemberVariableX); return genericMemberVariableT; } public T genericProperty { get; set; } }
Implementation:
MyGenericClass<int, string> intGenericClass = new MyGenericClass<int, string>(10, "Hello world"); int val = intGenericClass.genericMethod(200);
'IT' 카테고리의 다른 글
치명적인 오류 : 클래스에 구현되지 않은 초기화 프로그램 'init (coder :)'사용 (0) | 2020.06.07 |
---|---|
Github : 업스트림 분기를 포크로 가져 오기 (0) | 2020.06.07 |
Apache Commons equals / hashCode 빌더 (0) | 2020.06.07 |
ES6 모듈을 조건부로 가져 오려면 어떻게해야합니까? (0) | 2020.06.07 |
std :: vector가 push_back으로 객체를 복사합니까? (0) | 2020.06.07 |