C # Generics는 위임 형식 제약 조건을 허용하지 않습니다.
C #에서 클래스를 정의 할 수 있습니까?
class GenericCollection<T> : SomeBaseCollection<T> where T : Delegate
어젯밤 .NET 3.5에서이 작업을 수행 할 수 없었습니다. 나는 사용해 보았다
delegate, Delegate, Action<T> and Func<T, T>
이것이 어떤 식 으로든 허용되어야하는 것 같습니다. 내 EventQueue를 구현하려고합니다.
나는이 [원시적 인 근사화 마음 당신]을 끝냈습니다.
internal delegate void DWork();
class EventQueue {
private Queue<DWork> eventq;
}
그러나 다른 유형의 기능에 대해 동일한 정의를 재사용 할 수있는 능력을 잃게됩니다.
생각?
일반 제약으로 사용할 수없는 클래스가 많이 있습니다. Enum이 다른 것입니다.
델리게이트의 경우 가장 가까운 ": class"는 T 가 델리게이트 인지 확인하기 위해 (예 : 정적 생성자에서) 리플렉션을 사용합니다 .
static GenericCollection()
{
if (!typeof(T).IsSubclassOf(typeof(Delegate)))
{
throw new InvalidOperationException(typeof(T).Name + " is not a delegate type");
}
}
편집 : 다음 문서에서는 몇 가지 제안 된 해결 방법을 제안합니다.
http://jacobcarpenters.blogspot.com/2006/06/c-30-and-delegate-conversion.html
http://jacobcarpenters.blogspot.com/2006_11_01_archive.html
로부터 C # 2.0 사양 우리는 (20.7, 제약)를 읽을 수 있습니다 :
클래스 유형 제약 조건은 다음 규칙을 충족해야합니다.
- 유형은 클래스 유형이어야합니다.
- 유형은 봉인되지 않아야합니다.
- 형식은 System.Array, System.Delegate, System.Enum 또는 System.ValueType 형식 중 하나가 아니어야합니다 .
- 유형은 객체가 아니어야합니다. 모든 유형이 객체에서 파생되기 때문에 이러한 제약 조건은 허용되는 경우 효과가 없습니다.
- 주어진 유형 매개 변수에 대한 제한은 클래스 유형이 될 수 있습니다.
그리고 충분히 VS2008이 오류를 내뿜습니다.
error CS0702: Constraint cannot be special class 'System.Delegate'
이 문제에 대한 정보 및 조사는 여기를 참조하십시오 .
IL Weaver에 대한 컴파일 시간 의존성을 기꺼이 취하고 싶다면 Fody로 이것을 할 수 있습니다 .
이 추가 기능을 Fody https://github.com/Fody/ExtraConstraints에 사용
코드는 다음과 같습니다.
public class Sample
{
public void MethodWithDelegateConstraint<[DelegateConstraint] T> ()
{
}
public void MethodWithEnumConstraint<[EnumConstraint] T>()
{
}
}
그리고 이것으로 컴파일
public class Sample
{
public void MethodWithDelegateConstraint<T>() where T: Delegate
{
}
public void MethodWithEnumConstraint<T>() where T: struct, Enum
{
}
}
예, C # 7.3에서 가능하며 제약 조건 제품군은 Enum
, Delegate
및 unmanaged
형식 을 포함하도록 증가되었습니다 . 이 코드는 문제없이 작성할 수 있습니다.
void M<D, E, T>(D d, E e, T* t) where D : Delegate where E : Enum where T : unmanaged
{
}
유용한 링크:
Microsoft Build 2018 의 C # 미래
Delegate는 이미 연결을 지원합니다. 이것이 귀하의 요구를 충족하지 않습니까?
public class EventQueueTests
{
public void Test1()
{
Action myAction = () => Console.WriteLine("foo");
myAction += () => Console.WriteLine("bar");
myAction();
//foo
//bar
}
public void Test2()
{
Action<int> myAction = x => Console.WriteLine("foo {0}", x);
myAction += x => Console.WriteLine("bar {0}", x);
myAction(3);
//foo 3
//bar 3
}
public void Test3()
{
Func<int, int> myFunc = x => { Console.WriteLine("foo {0}", x); return x + 2; };
myFunc += x => { Console.WriteLine("bar {0}", x); return x + 1; };
int y = myFunc(3);
Console.WriteLine(y);
//foo 3
//bar 3
//4
}
public void Test4()
{
Func<int, int> myFunc = x => { Console.WriteLine("foo {0}", x); return x + 2; };
Func<int, int> myNextFunc = x => { x = myFunc(x); Console.WriteLine("bar {0}", x); return x + 1; };
int y = myNextFunc(3);
Console.WriteLine(y);
//foo 3
//bar 5
//6
}
}
I came across a situation where I needed to deal with a Delegate
internally but I wanted a generic constraint. Specifically, I wanted to add an event handler using reflection, but I wanted to use a generic argument for the delegate. The code below does NOT work, since "Handler" is a type variable, and the compiler won't cast Handler
to Delegate
:
public void AddHandler<Handler>(Control c, string eventName, Handler d) {
c.GetType().GetEvent(eventName).AddEventHandler(c, (Delegate) d);
}
However, you can pass a function that does the conversion for you. convert
takes a Handler
argument and returns a Delegate
:
public void AddHandler<Handler>(Control c, string eventName,
Func<Delegate, Handler> convert, Handler d) {
c.GetType().GetEvent(eventName).AddEventHandler(c, convert(d));
}
Now the compiler is happy. Calling the method is easy. For example, attaching to the KeyPress
event on a Windows Forms control:
AddHandler<KeyEventHandler>(someControl,
"KeyPress",
(h) => (KeyEventHandler) h,
SomeControl_KeyPress);
where SomeControl_KeyPress
is the event target. The key is the converter lambda - it does no work, but it convinces the compiler you gave it a valid delegate.
(Begin 280Z28) @Justin: Why not use this?
public void AddHandler<Handler>(Control c, string eventName, Handler d) {
c.GetType().GetEvent(eventName).AddEventHandler(c, d as Delegate);
}
(End 280Z28)
As mentioned above, you cannot have Delegates and Enum as a generic constraint. System.Object
and System.ValueType
also cannot be used as a generic constraint.
The work around can be if you construct an appropriate call in you IL. It will work fine.
Here is a good example by Jon Skeet.
http://code.google.com/p/unconstrained-melody/
I have taken my references from Jon Skeet's book C# in Depth, 3rd edition.
According to MSDN
Compiler Error CS0702
Constraint cannot be special class 'identifier' The following types may not be used as constraints:
- System.Object
- System.Array
- System.Delegate
- System.Enum
- System.ValueType.
참고URL : https://stackoverflow.com/questions/191940/c-sharp-generics-wont-allow-delegate-type-constraints
'program story' 카테고리의 다른 글
GCC 패드가 NOP와 함께 작동하는 이유는 무엇입니까? (0) | 2020.10.17 |
---|---|
RequireJS : "requirejs"와 "require"함수의 차이점 (0) | 2020.10.17 |
TikZ를 사용한 독립형 다이어그램? (0) | 2020.10.17 |
제네릭 클래스의 정적 멤버가 특정 인스턴스에 연결되어 있습니까? (0) | 2020.10.17 |
좋은 무료 소형 Python 웹 호스트가 있습니까? (0) | 2020.10.17 |