Working with object[] and List object

List<object> list = new List<object>();
list.Add(new object[]
{
     Convert.ToByte(1),  
     Convert.ToInt32(100), 
     Convert.ToString("test") 
});

I add object[] to the List object. How can I delete this object[]?

list.Remove(new object[]
{
    Convert.ToByte(1),  
    Convert.ToInt32(100), 
    Convert.ToString("test") 
}); //Это не работает

And how can I get the values from List object -> object [] - > for example the value of the string (I originally wrote the string " test")

 1

2 answers

In C#, object is a reference type, which means that when you create something via new, you get a new object, with the reference of which you continue and interact.

By writing

list.Add(new object[]
{
     Convert.ToByte(1),  
     Convert.ToInt32(100), 
     Convert.ToString("test") 
});

You create a new object object[], which is referenced in List<T>.

When you do

list.Remove(new object[]
{
    Convert.ToByte(1),  
    Convert.ToInt32(100), 
    Convert.ToString("test") 
});

Naturally, this will not work for you, since you are creating a completely new object whose reference will not be equal to the one you have in collections.

To delete an object from the collection, we need its index, or its reference, we can get the reference in many ways, even though var item = list[0];, for example, I will take LINQ and use it to delete an object that has the text test inside:

var searchItem = list.Where(x=>x is object[]).FirstOrDefault(x => ((object[])x).Contains("test"));

As a result, we will have either NULL, or the necessary reference to an object from the collection, which we can then safely delete using Remove().

As for getting the values, I think you're here on your own with your crutches You'll figure it out, I've already given you everything you need. Well, in general, I advise you to use something that is less dynamic or something, so you put a stick in your own wheels and do extra work.

 2
Author: EvgeniyZ, 2019-10-22 20:32:10

You don't need to work with object and arrays of this type.

Let me describe a little what was said in the comments.

Let's say there is a class

class CakeSet
{
    public int Id { get; set; }
    public string Value { get; set; }
}

Let's try to use it:

var cakes = new List<CakeSet>();
cakes.Add(new CakeSet { Id = 1, Value = "test" });
cakes.Remove(new CakeSet { Id = 1, Value = "test" });
Console.WriteLine(cakes.Count); // выведет 1

We added an instance of our class to the list and tried deleting another instance with the same property values. But the deletion did not happen. Why? Because it is another instance of the reference type. Their links are not equal - they are different.

What can be done. You can implement the Equals and GetHashCode methods in this class in such a way that the comparison of instances will occur not by reference, but based on the property values. For example, like this (the code is auto-generated):

class CakeSet
{
    public int Id { get; set; }
    public string Value { get; set; }

    public bool Equals(CakeSet other) =>
        Id == other.Id && string.Equals(Value, other.Value);

    public override bool Equals(object obj) =>
        obj is CakeSet other && Equals(other);

    public override int GetHashCode()
    {
        unchecked
        {
            return (Id * 397) ^ (Value != null ? Value.GetHashCode() : 0);
        }
    }
}

Now the above code will work - removal from the list will occur.


Another way is to use a structure (of a meaningful type) instead of a class.

struct CakeSet
{
    public int Id { get; set; }
    public string Value { get; set; }
}

Just change the keyword class in the type definition to struct and done. Tempting? Yes, but do not rush to do so. The use of structures is fraught with many problems. If you don't know how to work with meaningful types yet, then don't use them.


Another way, which was also mentioned in the comments: using tuples (tuple).
This is convenient because you don't need to create a class.

var list = new List<Tuple<byte, int, string>>();
list.Add(Tuple.Create((byte)1, 100, "test"));
list.Remove(Tuple.Create((byte)1, 100, "test"));
Console.WriteLine(list.Count); // 0

The tuple type is determined on the fly. At the same time, it provides strict typing (because of this, the unit has to be cast to byte).

The compiler automatically generates comparison methods (which we created ourselves for the class above) for tuples across all fields.


And finally, tuples of a significant type: ValueTuple.

var list = new List<(byte, int, string)>();
list.Add((1, 100, "test"));
list.Remove((1, 100, "test"));
Console.WriteLine(list.Count); // 0

The syntax is even simpler. But, again, you need to know their device under the hood to use it correctly and without errors.

In one short message, all the nuances can not be described. Read the documentation on structures and tuples before using them use.

 1
Author: Alexander Petrov, 2019-10-25 08:46:53