c# - 继承接口的结构数组似乎是引用类型
问题描述
我有一个名为Foo
and的结构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
(没有泛型)——它们都没有奏效。
知道这里发生了什么,以及如何仍然能够同时拥有一个数组Foo
和Bar
,两者都必须实现某些东西?
解决方案
如果没有您所看到的装箱,您就不能同时拥有 Foo 和 Bar 的数组,这两个结构都是如此。
如果将结构强制转换为接口,则会发生装箱,这发生在您创建 List<IFoo> 然后将结构放入其中时。您可以通过执行看到您的结构已成为引用类型
bool test = arr[0].GetType().IsValueType;
创建 arr 后:List<IFoo> 为 false,List<Foo> 为 true。
有一些解决方法,例如有两个数组,一个用于 Foo,一个用于 Bar,然后另一个数组用于索引到这两个数组。但这太可怕了。有关更多信息,请参阅早期的 Stack Overflow 答案。
由于所有这些,通常将接口放在结构上并不是一个好主意:结构旨在成为存在于堆栈上的轻量级事物。如果你需要这种行为,你最好使用类。
推荐阅读
- oracle - PL/SQL: 语句被忽略 06550. 00000 - “第 %s 行,第 %s 列:\n%s”
- php - php artisan migrate 未找到合适的服务器(`serverSelectionTryOnce` 集):[在 '10.0.0.106:27017' 上调用 ismaster 的连接超时]
- typescript - 如何将表单数据和本地存储数据存储到数据库
- knockout.js - 使用 Knockout 从元素获取有界属性
- python - 用python用文件名替换日志文件中的日期
- oracle - 一个更新语句中的oracle死锁?
- linux - 我在 ubuntu 中更新和安装新包时遇到问题
- google-apps-script - 如何修复:对 gmail.users.settings.filters.create 的 API 调用失败并出现错误:空响应
- ckeditor - 在 CKEditor 源模式下启用复制粘贴选项
- javascript - 如何在 JavaScript 中使这个异步查询同步?