从基类列表中返回引用将返回';什么都没有;

本文关键字:返回 什么 列表 基类 引用 | 更新日期: 2023-09-27 18:11:41

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

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

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

项目

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);
    }
}

用法

 QSingleItemsList xSingleList = new QSingleItemsList();
 xSingleList.add(new QSingleItem(5, 5));
 QSingleItem xFirst = new QSingleItem(0,0);
 xSingleList.getFirst(xFirst);

代码的最后一行应该(根据我的要求(在xFirst中包含(5,5(。但是,它包含(0,0(。当调试器位于XXX行时,xItems[0]和yFirst都是(5,5(。当代码返回到调用者(main(时,xFirst突然变成了(0,0(。为什么?

非常感谢您的帮助,Daniel

从基类列表中返回引用将返回';什么都没有;

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

public void getFirst(ref QAbstractItem yItem)

public void getFirst(out QAbstractItem yItem)

然后它会像这样被称为

QAbstractItem xFirst = new QSingleItem(0,0);
xSingleList.getFirst(ref xFirst);

让它发挥作用,但实际上它应该更接近

public QAbstractItem getFirst()

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

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

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

但是,在这种情况下,您将无法使用类型为QSingleItem的参数来调用它。


您的问题的另一种解决方案是使列表类通用:

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
    }
}

如果您需要针对给定类型的项的专用方法,可以将它们添加到继承泛型列表的类中:

public class QSingleItemsList : QItemsList<QSingleItem>
{
    // specialized methods here
}

问题出在该方法中:

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

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

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

public QAbstractItem getFirst()
{
    return xItems[0];        // XXX
}