2
votes

I'm a newcomer to C#, trying to learn Unity. I've tried to create a struct, and then extend an IList to contain it, but the struct's members don't seem to be detected. The list is for orders objects in an RTS game.

You can reproduce this with a new unity project, then creating two .cs files, HasFoo.cs and HasFooList.cs

HasFoo.cs:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    public struct HasFoo{
        public int foo;
        public HasFoo(bool constructor_parameter){
            foo = 1;
        }
    }

HasFooList.css:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    
    public class HasFooList<HasFoo> : IList<HasFoo>{
        private List<HasFoo> _list = new List<HasFoo>();
    
        public void Add(HasFoo item){
            item.foo = 2;
            this._list.Add(item);
        }
    
        #region Implementation of IEnumerable
    
        public IEnumerator<HasFoo> GetEnumerator()
        {
            return _list.GetEnumerator();
        }
    
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    
        #endregion
    
        #region Implementation of ICollection<HasFoo>
    
        public void Clear()
        {
            _list.Clear();
        }
    
        public bool Contains(HasFoo item)
        {
            return _list.Contains(item);
        }
    
        public void CopyTo(HasFoo[] array, int arrayIndex)
        {
            _list.CopyTo(array, arrayIndex);
        }
    
        public bool Remove(HasFoo item)
        {
            return _list.Remove(item);
        }
    
        public int Count
        {
            get { return _list.Count; }
        }
    
        public bool IsReadOnly
        {
            get { return _list.IsReadOnly; }
    
        }
    
        #endregion
    
        #region Implementation of IList<HasFoo>
    
        public int IndexOf(HasFoo item)
        {
            return _list.IndexOf(item);
        }
    
        public void Insert(int index, HasFoo item)
        {
            _list.Insert(index, item);
        }
    
        public void RemoveAt(int index)
        {
            _list.RemoveAt(index);
        }
    
        public HasFoo this[int index]
        {
            get { return _list[index]; }
            set { _list[index] = value; }
        }
    
        #endregion
    
    }

I get the following error messages:

Assets/HasFooList.cs(10,14): error CS1061: 'HasFoo' does not contain a definition for 'foo' and no accessible extension method 'foo' accepting a first argument of type 'HasFoo' could be found (are you missing a using directive or an assembly reference?)

Assets/HasFooList.cs(57,28): error CS1061: 'List' does not contain a definition for 'IsReadOnly' and no accessible extension method 'IsReadOnly' accepting a first argument of type 'List' could be found (are you missing a using directive or an assembly reference?)

If I change HasFooList's IsReadOnly to simply return false, that error goes away, but obviously isn't ideal.

1
Reason for first error: HasFooList<HasFoo>, so compiler think that HasFoo is a type parameter. Change this to public class HasFooList : IList<HasFoo>Aleks Andreev
Consider just using a List<HasFoo> rather than creating your own class, unless you have a very good reason for needing extra functionality. If you do, consider just using an extension method to a List<HasFoo> rather than burdening yourself with the mess of implementing IList<HasFoo>.Heretic Monkey
i'd be concerned here that you are using a struct and mutating it.Daniel A. White

1 Answers

1
votes

Your class shouldn't have a type argument but implement IList<HasFoo>:

public class HasFooList : IList<HasFoo> { ... }

If I change HasFooList's IsReadOnly to simply return false, that error goes away, but obviously isn't ideal.

Why not? HasFooList<HasFoo> is obviously not read-only so IsReadOnly should always return false in your case. The List<T>'s IsReadOnly does. If you want to access it, you need to cast _list to an ICollection<T> or IList because the property is explicitly implemented as you can see in the reference source.