C# 从基类列表返回引用将返回';没有';

C# 从基类列表返回引用将返回';没有';,c#,abstract-class,derived-class,C#,Abstract Class,Derived Class,我有几个共享类似功能的“项”,因此我从定义公共功能的基类派生它们 接下来,我还希望有这些项目的专门列表,因此我从抽象的基本容器派生类似容器的类 下面的代码演示了我的问题 项目 public abstract class QAbstractItem { public int xAbstractMember; public QAbstractItem(int a) { xAbstractMember = a; } } public class QS

我有几个共享类似功能的“项”,因此我从定义公共功能的基类派生它们

接下来,我还希望有这些项目的专门列表,因此我从抽象的基本容器派生类似容器的类

下面的代码演示了我的问题

项目

public abstract class QAbstractItem 
{
    public int xAbstractMember;
    public QAbstractItem(int a)
    {
        xAbstractMember = a;
    }
}

public class QSingleItem : QAbstractItem
{
    public int xSingleMember;
    public QSingleItem(int s, int a) : base(a)
    {
        xSingleMember = s;
    }
}
public abstract class QAbstractItemsList 
{
    public List<QAbstractItem> xItems = new List<QAbstractItem>();

    protected void add(QAbstractItem xItem)
    {
        xItems.Add(xItem);
    }

    public void getFirst(QAbstractItem yItem)
    {
        yItem = xItems[0];        // XXX
    }
}

public class QSingleItemsList : QAbstractItemsList
{
    public void add(QSingleItem S) 
    {
        base.add(S);
    }
}
列表

public abstract class QAbstractItem 
{
    public int xAbstractMember;
    public QAbstractItem(int a)
    {
        xAbstractMember = a;
    }
}

public class QSingleItem : QAbstractItem
{
    public int xSingleMember;
    public QSingleItem(int s, int a) : base(a)
    {
        xSingleMember = s;
    }
}
public abstract class QAbstractItemsList 
{
    public List<QAbstractItem> xItems = new List<QAbstractItem>();

    protected void add(QAbstractItem xItem)
    {
        xItems.Add(xItem);
    }

    public void getFirst(QAbstractItem yItem)
    {
        yItem = xItems[0];        // XXX
    }
}

public class QSingleItemsList : QAbstractItemsList
{
    public void add(QSingleItem S) 
    {
        base.add(S);
    }
}
最后一行代码应该(正如我所希望的)包含xFirst中的(5,5)。但是,它包含(0,0)。当调试器联机时,xItems[0]和yFirst都是(5,5)。当代码返回到调用方(main)时,xFirst突然变为(0,0)。为什么?

非常感谢您的帮助, 丹尼尔

yItem
参数按值传递(即使它是引用类型;引用按值传递)。因此,当您为yItem赋值时,调用者不会受到影响,因为
yItem
只包含原始引用的副本。要使其工作,您需要通过引用传递
yItem

public void getFirst(ref QAbstractItem yItem)
{
    yItem = xItems[0];        // XXX
}
但是,在本例中,您将无法使用类型为
QSingleItem
的参数调用它


您的问题的另一个解决方案是将list类设置为泛型:

public class QItemsList<TItem> where TItem : QAbstractItem
{
    public List<TItem> xItems = new List<TItem>();

    protected void add(TItem xItem)
    {
        xItems.Add(xItem);
    }

    public void getFirst(out TItem yItem)
    {
        yItem = xItems[0];        // XXX
    }
}
公共类QItemsList,其中TItem:QAbstractItem
{
public List xItems=新列表();
受保护的无效添加(TItem xItem)
{
xItems.Add(xItem);
}
公共无效getFirst(out TItem yItem)
{
yItem=xItems[0];//XXX
}
}
如果给定类型的项需要专用方法,可以将它们添加到继承泛型列表的类中:

public class QSingleItemsList : QItemsList<QSingleItem>
{
    // specialized methods here
}
公共类QSingleItemsList:QItemsList
{
//这里有专门的方法
}
yItem
参数按值传递(即使它是引用类型;引用按值传递)。因此,当您为yItem赋值时,调用者不会受到影响,因为
yItem
只包含原始引用的副本。要使其工作,您需要通过引用传递
yItem

public void getFirst(ref QAbstractItem yItem)
{
    yItem = xItems[0];        // XXX
}
但是,在本例中,您将无法使用类型为
QSingleItem
的参数调用它


您的问题的另一个解决方案是将list类设置为泛型:

public class QItemsList<TItem> where TItem : QAbstractItem
{
    public List<TItem> xItems = new List<TItem>();

    protected void add(TItem xItem)
    {
        xItems.Add(xItem);
    }

    public void getFirst(out TItem yItem)
    {
        yItem = xItems[0];        // XXX
    }
}
公共类QItemsList,其中TItem:QAbstractItem
{
public List xItems=新列表();
受保护的无效添加(TItem xItem)
{
xItems.Add(xItem);
}
公共无效getFirst(out TItem yItem)
{
yItem=xItems[0];//XXX
}
}
如果给定类型的项需要专用方法,可以将它们添加到继承泛型列表的类中:

public class QSingleItemsList : QItemsList<QSingleItem>
{
    // specialized methods here
}
公共类QSingleItemsList:QItemsList
{
//这里有专门的方法
}

您对
getFirst
的实现不正确。您需要向其中添加ref或out关键字。关键字表示可以重新分配传入的值,关键字表示忽略输入值,结果将分配到那里

public void getFirst(参考qabstractem yItem)

public void getFirst(out qabstractem yItem)

然后它会被这样称呼

QAbstractItem xFirst = new QSingleItem(0,0);
xSingleList.getFirst(ref xFirst);
让它工作,但实际上它应该更接近


public QAbstractItem getFirst()

您对
getFirst
的实现不正确。您需要向其中添加ref或out关键字。关键字表示可以重新分配传入的值,关键字表示忽略输入值,结果将分配到那里

public void getFirst(参考qabstractem yItem)

public void getFirst(out qabstractem yItem)

然后它会被这样称呼

QAbstractItem xFirst = new QSingleItem(0,0);
xSingleList.getFirst(ref xFirst);
让它工作,但实际上它应该更接近


public QAbstractItem getFirst()

该方法存在问题:

您必须知道,当您将参数传递给方法时,将创建对
yItem
的引用的副本。因此,如果将新值赋给
yItem
,它对传递给方法
getFirst
的实际参数没有影响。 根据C#规范,这是正确的行为

可以考虑更改方法返回第一个元素:


问题在于这种方法:

您必须知道,当您将参数传递给方法时,将创建对
yItem
的引用的副本。因此,如果将新值赋给
yItem
,它对传递给方法
getFirst
的实际参数没有影响。 根据C#规范,这是正确的行为

可以考虑更改方法返回第一个元素:


正如Thomas Levesque指出的那样,ref/out的问题在于它不适用于抽象类。对于实际应用程序中的
public QAbstractItem getFirst()
,我需要获得一对特定的qsingleItem,因此我在参数中“返回它们”。@DanielBencik返回包含这对对象的对象可能比使用
out
/
ref
@DanielBencik如果您失去了我,getFirst只给你一件事。您的意思是要将它们作为类型
QSingItem
而不是作为
QAbstractItem
获取吗?@Sign:是的,getFirst是为演示而编写的。实际上,我希望有类似于
getSomeTwo()
,即我需要返回一对特别选择的qsingleitem.\@DanielBencik那么为什么不返回一个
元组呢?或者其他更具体的东西同时包含这两者?ref/out的问题是它不能处理抽象类,正如Thomas Levesque也指出的那样。对于实际应用程序中的
public qabstracttem getFirst()
,我需要获得一个特定的对