[英]"Dereference" var in C#
我在 C# 中有一些代码使用这样的结构:
ArrayList addrs = new ArrayList();
byte[] addr = new byte[8];
while (oneWire.Search_GetNextDevice(addr))
{
addrs.Add(addr);
}
在此示例中, ArrayList
中的每个元素都与找到的最后一个设备相同,因为它看起来好像addr
是通过引用传递出去的,我只是将该引用复制到ArrayList
中。
有什么方法可以“取消引用” addr
来只提取它的价值吗?
也有可能我对情况的评估不正确,如果情况似乎是这样,请告诉我
谢谢!
如果addr
是一个类变量(而不是struct),它将显示出来。
在这种情况下, Search_GetNextDevice()
将Search_GetNextDevice()
填充相同的实例。
您也许可以用类似的方法解决它
byte[] addr = new byte[8];
while (oneWire.Search_GetNextDevice(addr))
{
addrs.Add(addr);
addr = new byte[8];
}
更新为byte[]
info
您可能需要像addrs.Add(addr.Clone());
类的东西addrs.Add(addr.Clone());
创建addr
的副本(或克隆)以放入列表中。
如果addr是一个结构,则可能会出现多个问题。
首先,addr不会更改,如果必须更改,则需要声明Search_GetNextDevice
作为引用。
如果要在Search_GetNextDevice
中更改addr.something
值,那么您将不会在副本中看到这些值。由于将结构按值传递给方法,因此它们将丢失。
转换为数组,然后循环复制:
ArrayList addrs = new ArrayList();
while (oneWire.Search_GetNextDevice(addr.ToArray((whateverTypeYourItemsHave[])typeof(whateverTypeYourItemsHave))))
{
addrs.Add(addr);
}
如果您知道列表中的项目是更好的方法,则使用通用列表。 读起来更好,更不易出错:
List<whateverYourItemTypeIs> addrs = new List<whateverYourItemTypeIs>();
while (oneWire.Search_GetNextDevice(addr.ToArray()))
{
addrs.Add(addr);
}
对于引用类型,您最终必须克隆 object。大多数类都没有内置方法,但有一个数组,已接受的答案适当地显示了这一点。
一种选择(对于那些不使用数组的人)是从 JSON 或 MessagePack 等格式进行序列化和反序列化。 这适用于某些类型。 (一个 POCO class 可以序列化为 JSON,并且可以 IEnumerables)。 您可以使用这样的方法通过序列化克隆 object:
internal static class CloneHelper
{
public static T Clone<T>(this T item) where T : class, new()
{
var asString = JsonSerializer.Serialize(item);
var newObject = JsonSerializer.Deserialize<T>(asString);
if (newObject is null)
{
throw new Exception("Something went wrong in serialization");
}
return newObject;
}
}
如果你想模拟 C# 9 记录克隆功能( with
关键字),你可以做这样的事情(可能不会在生产中这样做)。
internal static class CloneHelper
{
public static T Clone<T>(this T item, object? with = null) where T : class, new()
{
var asString = JsonSerializer.Serialize(item);
var newObject = JsonSerializer.Deserialize<T>(asString);
if (newObject is null)
{
throw new Exception("Something went wrong in serialization");
}
if (with is not null)
{
foreach (var property in with.GetType().GetProperties())
{
var val = property.GetValue(with);
typeof(T).GetProperties()
.FirstOrDefault(x => x.Name == property.Name
&& ReferenceEquals(x.PropertyType, property.PropertyType))
?.SetValue(newObject, val);
}
}
return newObject;
}
}
然而,序列化和反射都很慢,而且不是 100% 类型安全的,所以不要在性能关键或安全关键的情况下这样做。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.