none
关于逆变转协变的问题 RRS feed

  • 问题

  • 这个是模型

    public abstract class BaseModel { }

        public class Model : BaseModel
        {
        }

        public interface IUCOut<out T> where T : BaseModel
        {
            IEnumerable<T> GetList();
            void SetMyControl(IUCIn<T> my);
        }
    
        public interface IUCIn<in T> where T : BaseModel
        {
            void AddItems(IEnumerable<T> items);
            void RemoveItemAt(int index);
            void MoveItemSquence(int index, string direction);
        }
    public partial class UC1 : IUCIn<Model>,IUCOut<Model>
        {
    
            #region IUCIn<Model> 成员
             …………
            #endregion
    
            #region IUCOut<Model> 成员
    
            public IEnumerable<Model> GetList()
            {
                throw new NotImplementedException();
            }
    
            public void SetMyControl(IUCIn<Model> my)
            {
                my = this;//转出来的为空
            }
    
            #endregion
    IUCOut<BaseModel> _out = UC1 as IUCOut<BaseModel>;//协变
    IUCIn<BaseModel> _in; 
    _out.SetMyControl(_in);//将UC1对像转为逆变是返回空



    2012年5月24日 14:15

全部回复

  • 您好,请使用ref。

    public void SetMyControl(ref IUCIn<Model> my)
    {
    	my = this;//转出来的为空
    }
    
    UC1 myUc1 = new UC1();
    IUCOut<BaseModel> _out = myUc1 as IUCOut<BaseModel>;//协变
    IUCIn<Model> _in = null;
    myUc1.SetMyControl(ref _in); //将UC1对像转为逆变是返回空


    以上說明若有錯誤請指教,謝謝。
    亂馬客blog: http://www.dotblogs.com.tw/rainmaker/

    2012年5月25日 5:11
  • 不为空啊!你看我输出的!

    namespace BinarySearch
    {
        public abstract class BaseModel
        { 
        }
        public class Model : BaseModel
        {
        }

        public interface IUCOut<out T> where T : BaseModel
        {
            IEnumerable<T> GetList();
            void SetMyControl(IUCIn<T> my);
        }

        public interface IUCIn<in T> where T : BaseModel
        {
            void AddItems(IEnumerable<T> items);
            void RemoveItemAt(int index);
            void MoveItemSquence(int index, string direction);
        }

        public partial class UC1 : IUCIn<Model>,IUCOut<Model>
        {
            public IEnumerable<Model> GetList()
            {
                return null;
            }

            public void SetMyControl(IUCIn<Model> my)
            {
                my = this;//
                Console.WriteLine((my == null).ToString());
            }

            public void AddItems(IEnumerable<Model> items)
            {
                throw new NotImplementedException();
            }

            public void RemoveItemAt(int index)
            {
                throw new NotImplementedException();
            }

            public void MoveItemSquence(int index, string direction)
            {
                throw new NotImplementedException();
            }
        }


        class Program
        {
            static void Main(string[] args)
            {
                UC1 uc1 = new UC1();
                IUCOut<BaseModel> _out = uc1 as IUCOut<BaseModel>;//协变
                IUCIn<BaseModel> _in = null;
                _out.SetMyControl(_in);
            }
        }
    }


       QQ我:讨论(Talk)
    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处

    2012年5月25日 5:13
    版主
  • 楼主:)

    这个和协变和反变似乎没有什么关系……你要记住——函数参数无论是传值还是传值(引用对象),函数参数都不是原来的那个版本,是赋值的。你可以把

    (IUCIn<Model> my)

    理解成一个副本,相当于内存中开辟了一个my的指针对象指向了this(自身),但是一旦出了函数体,my自动

    被释放了。

    注意:引用指针指向的对象是同一个对象(同一引用!),但是“指针”并不是同一个,一旦

    改变了指针的指向对象,自然不是同一引用了,何况函数内的参数出了函数就无效咯


       QQ我:讨论(Talk)
    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处

    2012年5月25日 6:15
    版主
  • 在MSDN中,接口不是阐述为引用类型的么?

    还是由于定义In的原因呢?

    2012年5月25日 10:48
  • 在MSDN中,接口不是阐述为引用类型的么?

    还是由于不是定义In的原因呢?

    不是,这和In没有关系——你记住:

    引用类型的定义是:对相同引用的对象,一方发生了改变,另一方也同步发生改变。

    现在你看:

    public void SetMyControl(IUCIn<Model> my)
    {
    	my = this;//转出来的为空
    }

    假设主函数有一个接口(指针)引用a,传入SetMyControl中。那么内存中my=a(也就是my指向a)。

    但是函数体内my=this(my的指针已经改变方向了)。此时a还是a自身,为空。

    那么退出函数体之后,a还是a(my是函数传址,自然随着函数调用结束而结束)。


       QQ我:讨论(Talk)
    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处

    2012年5月26日 0:49
    版主
  • 不能使用使用ref关键字的。

    我的接口定义为协变,但是void SetMyControl(ref IUCIn<Model> my)是逆变了
    不能正确编译的。

    还没能理解逆变和协变之间的转化关系。

    2012年6月1日 3:34
  • 这和逆变什么没有直接关系,请看我的回答——这是一个很特殊的“多个引用指针是否指向同一个对象”的问题。

       QQ我:讨论(Talk)
    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处

    2012年6月1日 4:42
    版主
  • LZ好像没有理解 C#中 协变和逆变的概念

    这里有一篇文章解释得很清楚:深入理解 C# 协变和逆变


    给我写信: QQ我:点击这里给我发消息

    2012年6月4日 12:20
  • 简单的说, 协变向上转型,将子类转为父类对象的引用;逆变向下转型,将父类具体化为一个子类。因此,协变类型参数可用作泛型委托或泛型接口的返回类型,而逆变类型参数可用作参数类型。发生协变时,需要进行强制转换。


    你必须非常努力,才能看起来毫不费力

    2012年6月14日 15:15