继承接口的结构数组似乎是引用类型



我有一个名为FooBar的结构,如果这两个结构都实现了一个称为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"

如果我有一个只有FooBar的数组,我就没有这个问题——只有当我有IFoo的数组时。我还尝试过普通数组(类型为"object")和ArrayList(没有泛型),但都不起作用

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

如果没有所看到的装箱,就不可能同时拥有Foo和Bar这两种结构的数组。

如果将结构强制转换为接口,则会出现装箱,当创建List<IFoo>然后把你的结构放进去。你可以通过看到你的结构已经变成了引用类型

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

在您创建arr之后:对于List<IFoo>并且对于List<Foo>。

有一些变通方法,比如有两个数组——一个用于Foo,一个用于Bar,然后用另一个数组对这两个数组进行索引。但这太可怕了。有关更多信息,请参阅前面的"堆栈溢出"回答。

由于所有这些,通常在structs上放置接口不是一个好主意:structs旨在成为栈上的轻量级对象。如果你需要这种行为,你最好使用类。

通过将值类型存储在接口类型的变量中,它会被装箱。接口总是引用类型,因此隐式地将实现它的值类型转换为接口的类型需要将其装箱。装箱的值类型是引用类型,所以您观察的是引用类型行为,因为arr[0]实际上是引用类型

最新更新