Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/270.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何将对象强制转换为其自己的类型?_C#_Generics_Casting - Fatal编程技术网

C# 如何将对象强制转换为其自己的类型?

C# 如何将对象强制转换为其自己的类型?,c#,generics,casting,C#,Generics,Casting,我已经读了好几篇关于这个问题的帖子,但是没有一个答案适合我。情况是这样的--我有一个泛型函数要在另一个类中调用: public class Dispatcher<T> where T : Event { public void Notify<X>(X tEvent) where X : Event { if (someField is IListener<X, T>) { //this never execut

我已经读了好几篇关于这个问题的帖子,但是没有一个答案适合我。情况是这样的--我有一个泛型函数要在另一个类中调用:

public class Dispatcher<T> where T : Event {
    public void Notify<X>(X tEvent) where X : Event {
        if (someField is IListener<X, T>) {
             //this never executes--X is Event regardless of its derived type
        }
    }
}
问题是Event有几十个派生类型,我需要Notify()调用,派生类型为X。到目前为止,无论传入何种类型的事件,它都只调用Notify()。编译的唯一解决方案是调用Notify(myEvent作为DerivedEvent),但这必须针对每种类型进行硬编码——这是不可接受的

如果我从派生类的实例给它一个“this”指针,类似的函数会正确地推断


当然这里有一个使用反射的解决方案。

您是否可以删除约束并检查以确保它源自
事件,如下所示:

public class Dispatcher<T> where T : Event {
    public void Notify<X>(X tEvent) {
        if(typeof(tEvent).IsSubclassOf(typeof(Event))
        {
            if (someField is IListener<X, T>) {
                //this never executes--X is Event regardless of its derived type
            }
        }
    }
}
公共类调度程序,其中T:Event{
公共无效通知(X tEvent){
if(类型(事件).IsSubclassOf(类型(事件))
{
如果(某个字段是IListener){
//这永远不会执行--X是事件,无论其派生类型如何
}
}
}
}

您是否可以删除约束并检查以确保它源自
事件,如下所示:

public class Dispatcher<T> where T : Event {
    public void Notify<X>(X tEvent) {
        if(typeof(tEvent).IsSubclassOf(typeof(Event))
        {
            if (someField is IListener<X, T>) {
                //this never executes--X is Event regardless of its derived type
            }
        }
    }
}
公共类调度程序,其中T:Event{
公共无效通知(X tEvent){
if(类型(事件).IsSubclassOf(类型(事件))
{
如果(某个字段是IListener){
//这永远不会执行--X是事件,无论其派生类型如何
}
}
}
}
您有两个问题

首先,您的泛型正在泄漏。每当您需要确定特定实例的类型时,您的函数不再是泛型的。请考虑您的设计缺陷并重新检查您正在尝试做什么。

其次,
IListener
不是类型。泛型在.NET中不是泛型的;运行时确定应用程序需要的所有实际类型并创建它们。例如,如果您在应用程序中实际使用类型
IListener
,runtim将创建该类型

var foo = new List<int>();
var bar = foo.GetType() == typeof(List<>);
var foo=newlist();
var bar=foo.GetType()==typeof(列表);
在本例中,
bar
false

即使有了这些,是的,这也是可能的。您只需要了解泛型类型定义的反射是如何工作的

我强烈建议您重新考虑以这种方式使用泛型。有时抽象和荒谬并不是最好的事情…

您有两个问题

首先,您的泛型正在泄漏。每当您需要确定特定实例的类型时,您的函数不再是泛型的。请考虑您的设计缺陷并重新检查您正在尝试做什么。

其次,
IListener
不是类型。泛型在.NET中不是泛型的;运行时确定应用程序需要的所有实际类型并创建它们。例如,如果您在应用程序中实际使用类型
IListener
,runtim将创建该类型

var foo = new List<int>();
var bar = foo.GetType() == typeof(List<>);
var foo=newlist();
var bar=foo.GetType()==typeof(列表);
在本例中,
bar
false

即使有了这些,是的,这也是可能的。您只需要了解泛型类型定义的反射是如何工作的


我强烈建议您重新考虑以这种方式使用泛型。有时抽象和荒谬并不是最好的事情…

为了像您期望的那样调用它,您必须使用反射来生成myEvent的实际类型的方法。但我要强调的是,执行以下操作是一个坏主意,可能意味着我们的设计需要重新考虑

MethodInfo openGenericMethod = OtherClass.GetType().GetMethod("Notify");
MethodInfo closedGenericMethod = openGenericMethod.MakeGenericMethod(myEvent.GetType());

closedGenericMethod.Invoke(OtherClass, new object[]{ myEvent });, 

我并没有实际测试上面的代码,但它看起来是这样的,为了像您期望的那样调用它,您必须使用反射来生成myEvent的实际类型的方法。但是我要强调的是,执行以下操作是一个坏主意,可能意味着您的设计需要重新考虑

MethodInfo openGenericMethod = OtherClass.GetType().GetMethod("Notify");
MethodInfo closedGenericMethod = openGenericMethod.MakeGenericMethod(myEvent.GetType());

closedGenericMethod.Invoke(OtherClass, new object[]{ myEvent });, 

我实际上没有测试上面的代码,但它看起来是这样的,所以我似乎找到了另一端的解决方法

public class Dispatcher<T> where T : Event {
    public void Notify<X>(X tEvent) where X : Event {
        foreach (Object l in listeners) {
            if (l is IListener<X, T>) { //never true
                (l as IListener<X, T>).OnEvent();
            }
        }
    }
}
公共类调度程序,其中T:Event{
公共无效通知(X tEvent),其中X:事件{
foreach(侦听器中的对象l){
如果(l是线性的){//永远不会为真
(l作为IListener.OnEvent();
}
}
}
}
我有一个烂摊子:

public class Dispatcher<T> where T : Event {
    public void Notify<X>(X tEvent) where X : Event {
        foreach (Object l in listeners) {
            foreach (Type t in l.GetType().GetInterfaces()) {
                Type[] temp = t.GetGenericArguments();
                if (temp.Count() > 0 && temp[0] == tEvent.GetType()) {
                    MethodInfo mi = t.GetMethod("OnEvent", new Type[] {tEvent.GetType()});
                    mi.Invoke(l, new object[] { tEvent });
                }
            }
        }
    }
}
公共类调度程序,其中T:Event{
公共无效通知(X tEvent),其中X:事件{
foreach(侦听器中的对象l){
foreach(在l.GetType().GetInterfaces()中键入t){
类型[]temp=t.GetGenericArguments();
if(temp.Count()>0&&temp[0]==tEvent.GetType()){
MethodInfo mi=t.GetMethod(“OnEvent”,新类型[]{tEvent.GetType()});
调用(l,新对象[]{tEvent});
}
}
}
}
}

虽然我不喜欢测试每个界面(Windows窗体至少有10个界面),但这似乎是可行的。我将尝试BrandonAGr的解决方案,因此我似乎已经找到了另一端的解决方法。而不是

public class Dispatcher<T> where T : Event {
    public void Notify<X>(X tEvent) where X : Event {
        foreach (Object l in listeners) {
            if (l is IListener<X, T>) { //never true
                (l as IListener<X, T>).OnEvent();
            }
        }
    }
}
公共类调度程序,其中T:Event{
公共无效通知(X tEvent),其中X:事件{
foreach(侦听器中的对象l){
如果(l是线性的){//永远不会为真
(l作为IListener.OnEvent();
}
}
}
}
我有一个烂摊子:

public class Dispatcher<T> where T : Event {
    public void Notify<X>(X tEvent) where X : Event {
        foreach (Object l in listeners) {
            foreach (Type t in l.GetType().GetInterfaces()) {
                Type[] temp = t.GetGenericArguments();
                if (temp.Count() > 0 && temp[0] == tEvent.GetType()) {
                    MethodInfo mi = t.GetMethod("OnEvent", new Type[] {tEvent.GetType()});
                    mi.Invoke(l, new object[] { tEvent });
                }
            }
        }
    }
}
公共类调度程序,其中T:Event{
公共无效通知(X tEvent),其中X:事件{
foreach(侦听器中的对象l){
foreach(在l.GetType().GetInterfaces()中键入t){
类型[]temp=t.GetGenericArguments();
if(temp.Count()>0&&temp[0]==tEvent.GetType()){
MethodInfo mi=t.GetMethod(“OneEvent”,新类型[]{t