如何转换'这个' in" Self Referencing Generics"

时间:2014-10-17 04:50:08

标签: c# generics delegates

我想在我的模型中添加一个观察者,我尝试通用委托,但这在调用时是个问题。

这是我的代码,当我使用'handler.DynamicInvoke(this)'代替'Invoke'

时,它可以正常工作

但我知道DynamicInvoke很慢......我想知道这是使用Invoke的正确方法。

public class Model<T>
{
    public delegate void UpdatePrototype<T>(T mdl);

    private List<UpdatePrototype<T>> listeners = new List<UpdatePrototype<T>>();
    public void Bind(UpdatePrototype<T> handler)
    {
        listeners.Add(handler);
    }

    public void Sync()
    {
        foreach(UpdatePrototype<T> handler in listeners)
        {
            handler.Invoke((T)this); // << ERROR: can not convert Model<T> to T
        }
    }

    public string Name = "Model";
}

public class MyModel : Model<MyModel>
{
    public string Name = "MyModel";
}

public class YourModel : Model<YourModel>
{
    public string Name = "YourModel";
}

void Main()
{
    MyModel mdl = new MyModel();
    mdl.Bind(MyUpdate);
    mdl.Sync();

    YourModel your = new YourModel();
    your.Bind(YourUpdate);
    your.Sync();
}

void MyUpdate(MyModel mdl)
{
    Debug.Log(mdl.Name);
}

void YourUpdate(YourModel mdl)
{
    Debug.Log(mdl.Name);
}

============

感谢@ IVAAAN123我修改我的代码如下。

对我来说没问题,虽然mdl.Sync<MyModel>()有点奇怪;)

public class Model<T>
{
    public delegate void UpdatePrototype<T>(T mdl);

    private List<UpdatePrototype<T>> listeners = new List<UpdatePrototype<T>>();
    public void Bind(UpdatePrototype<T> handler)
    {
        listeners.Add(handler);
    }

    public void Sync()
    {
        foreach(UpdatePrototype<T> handler in listeners)
        {
            handler.DynamicInvoke(this);
        }
    }
    public void Sync<T>() where T : Model<T>
    {
        foreach(UpdatePrototype<T> handler in listeners)
        {
            handler.Invoke((T)this);
        }
    }

    public string Name = "Model";
}

public class MyModel : Model<MyModel>
{
    public string Name = "MyModel";
}

public class YourModel : Model<YourModel>
{
    public string Name = "YourModel";
}

void Main()
{
    MyModel mdl = new MyModel();
    mdl.Bind(MyUpdate);
    mdl.Sync<MyModel>();
    mdl.Sync();

    YourModel your = new YourModel();
    your.Bind(YourUpdate);
    your.Sync<YourModel>();
    your.Sync();
}

void MyUpdate(MyModel mdl)
{
    Debug.Log(mdl.Name);
}

void YourUpdate(YourModel mdl)
{
    Debug.Log(mdl.Name);
}

}

1 个答案:

答案 0 :(得分:0)

        public class Model<T>
        {
            public delegate void UpdatePrototype<S>(S mdl);

            private List<UpdatePrototype<Model<T>>> listeners = new List<UpdatePrototype<Model<T>>>();
            public void Bind(UpdatePrototype<Model<T>> handler)
            {
                listeners.Add(handler);
            }

            public void Sync()
            {
                foreach (UpdatePrototype<Model<T>> handler in listeners)
                {
                    handler(this);
                }
            }

            public virtual string Name
            {
                get
                {
                    return "Model";
                }
            }
        }

        public class MyModel : Model<MyModel>
        {
            public override string Name
            {
                get
                {
                    return "MyModel";
                }
            }
        }

        public class YourModel : Model<YourModel>
        {
            public override string Name
            {
                get
                {
                    return "YourModel";
                }
            }
        }

        void main()
        {
            MyModel mdl = new MyModel();
            mdl.Bind(MyUpdate);
            mdl.Sync();

            YourModel your = new YourModel();
            your.Bind(YourUpdate);
            your.Sync();
        }

        void MyUpdate(Model<MyModel> mdl)
        {
            Console.WriteLine("MY MODEL HANDLER");
            Console.WriteLine(mdl.Name);
        }

        void YourUpdate(Model<YourModel> mdl)
        {
            Console.WriteLine("YOUR MODEL HANDLER");
            Console.WriteLine(mdl.Name);
        }