首页 > 解决方案 > 继承接口的结构数组似乎是引用类型

问题描述

我有一个名为Fooand的结构Bar- 如果它们都实现了一个名为IFoo.

public interface IFoo
{
    string StrTest { get; set; }
    int NumTest { get; set; }
}

public struct Foo : IFoo
{
    public Foo(string backTest, int numTest)
    {
        StrTest = backTest;
        NumTest = numTest;
    }

    public string StrTest { get; set; }
    public int NumTest { get; set; }
}

public struct Bar : IFoo
{
    public Bar(string backTest, int numTest)
    {
        StrTest = backTest;
        NumTest = numTest;
    }

    public string StrTest { get; set; }
    public int NumTest { get; set; }
}

假设我有一个数组IFoo,在索引“0”处我有一个Foo结构。当我将该结构移至新索引时出现问题 - 例如“1”(应该复制它)。现在,您会期望它们都是分开的,这意味着您更改了一个,而另一个也不应该更改。

但是,我发现如果我更改新移动的属性之一 - 两者都更改......这不是class(引用类型)功能吗?

看看下面的例子:

// Create a list of "BackInterface"s - with foo and bar.
List<IFoo> arr = new List<IFoo>
{
    new Foo("A", 2),
    new Bar("B", 4)
};

// Now, place the SAME struct at index "0" (the foo) at the end - it should be copied?
arr.Add(arr[0]);

// Modify the item at the last newly-created index
arr[2].StrTest = "C";

arr[0]和现在都是。arr[2]_StrTest"C"

如果我有一个 just 数组Foo或者Bar我没有这个问题 - 只有当我有一个IFoo. 我也尝试过普通数组(类型为 " object)和ArrayList(没有泛型)——它们都没有奏效。

知道这里发生了什么,以及如何仍然能够同时拥有一个数组FooBar,两者都必须实现某些东西?

标签: c#struct

解决方案


如果没有您所看到的装箱,您就不能同时拥有 Foo 和 Bar 的数组,这两个结构都是如此。

如果将结构强制转换为接口,则会发生装箱,这发生在您创建 List<IFoo> 然后将结构放入其中时。您可以通过执行看到您的结构已成为引用类型

bool test = arr[0].GetType().IsValueType; 

创建 arr 后:List<IFoo> 为 false,List<Foo> 为 true。

有一些解决方法,例如有两个数组,一个用于 Foo,一个用于 Bar,然后另一个数组用于索引到这两个数组。但这太可怕了。有关更多信息,请参阅早期的 Stack Overflow 答案

由于所有这些,通常将接口放在结构上并不是一个好主意:结构旨在成为存在于堆栈上的轻量级事物。如果你需要这种行为,你最好使用类。


推荐阅读