繁体   English   中英

C# 中的“取消引用”var

[英]"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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM