开发者

"Dereference" var in C#

开发者 https://www.devze.com 2023-02-04 04:51 出处:网络
I have some code in C# that uses a structure as such: ArrayList addrs = new ArrayList(); byte[] addr = new byte[8];

I have some code in C# that uses a structure as such:

ArrayList addrs = new ArrayList();
byte[] addr = new byte[8];
while (oneWire.Search_GetNextD开发者_如何学Goevice(addr))
{
    addrs.Add(addr);
}

In this example, every element in the ArrayList is the same as the last device that was found because it would appear as though addr is passed out by reference and I am simply copying that reference into the ArrayList.

Is there any way to "Dereference" addr to only extract it's value?

It's also possible my assessment of the situation is incorrect, if that appears to be the case, please let me know

Thanks!


If addr is a class variable (and not a struct) it would figure.

In that case Search_GetNextDevice() would be filling the same instance over and over.

You might be able to solve it with something like

byte[] addr = new byte[8];
while (oneWire.Search_GetNextDevice(addr))
{
   addrs.Add(addr);
   addr = new byte[8];
}

updated with the byte[] info


You probably need something like addrs.Add(addr.Clone()); to create a copy (or clone) of addr to put in your list.


if addr is a structure, then there are multiple problems can arise.

First of all, addr will not change and if it has to change then you need to declare Search_GetNextDevice as a ref.

If you are changing values of addr.something in Search_GetNextDevice, then you will notsee those values in the copy you have.They will be lost since structures are passed by value to the methods.


Convert to array, then loop that copy:

 ArrayList addrs = new ArrayList();
        while (oneWire.Search_GetNextDevice(addr.ToArray((whateverTypeYourItemsHave[])typeof(whateverTypeYourItemsHave))))
        {
            addrs.Add(addr);
        }

Or better if you know what the items in your list are, use generic list. Better to read, less error prone:

List<whateverYourItemTypeIs> addrs = new List<whateverYourItemTypeIs>();
        while (oneWire.Search_GetNextDevice(addr.ToArray()))
        {
            addrs.Add(addr);
        }


With reference types, you ultimately have to clone the object. There is not a built-in way for most classes, though there is for an array, which the Accepted Answer shows appropriately.

One option (for those not using an array) is to serialize and deserialize from a format like JSON or MessagePack. This works for some types. (a POCO class can be serialized to JSON, and can IEnumerables). You can use a method like this to clone an object via serialization:

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;
    }
}

If you want to simulate C# 9 record cloning functionality (with keyword), you can do something like this (probably don't do this in production).

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;
    }
}

However, serialization and reflection are both slow and not 100% type-safe, so don't do this in performance critical or safety critical situation.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号