1
public class CubicMatrix<Object?>
    {
        private int width;
        private int height;
        private int depth;
        private Object[, ,] matrix;

        public CubicMatrix(int inWidth, int inHeight, int inDepth)
        {
            width = inWidth;
            height = inHeight;
            depth = inDepth;
            matrix = new Object[inWidth, inHeight, inDepth];
        }

        public void Add(Object toAdd, int x, int y, int z)
        {
            matrix[x, y, z] = toAdd;
        }

        public void Remove(int x, int y, int z)
        {
            matrix[x, y, z] = null;
        }

        public void Remove(Object toRemove)
        {
            for (int x = 0; x < width; x++)
            {
                for (int y = 0; y < height; y++)
                {
                    for (int z = 0; z < depth; z++)
                    {
                        Object value = matrix[x, y, z];
                        bool match = value.Equals(toRemove);
                        if (match == false)
                        {
                            continue;
                        }

                        matrix[x, y, z] = null;
                    }
                }
            }
        }

        public IEnumerable<Object> Values
        {
            get
            {
                LinkedList<Object> allValues = new LinkedList<Object>();
                foreach (Object entry in matrix)
                {
                    allValues.AddLast(entry);
                }
                return allValues.AsEnumerable<Object>();
            }
        }

        public Object this[int x, int y, int z]
        {
            get
            {
                return matrix[x, y, z];
            }
        }

        public IEnumerable<Object> RangeInclusive(int x1, int x2, int y1, int y2, int z1, int z2)
        {
            LinkedList<Object> list = new LinkedList<object>();
            for (int a = x1; a <= x2; a++)
            {
                for (int b = y1; b <= y2; b++)
                {
                    for (int c = z1; c <= z2; c++)
                    {
                        Object toAdd = matrix[a, b, c];
                        list.AddLast(toAdd);
                    }
                }
            }

            return list.AsEnumerable<Object>();
        }

        public bool Available(int x, int y, int z)
        {
            Object toCheck = matrix[x, y, z];
            if (toCheck != null)
            {
                return false;
            }

            return true;
        }
    }

I've created a Cubic Matrix class in C# to store items in 3 dimensions. I need to be able to add and remove items which is why I'm using Object? (I've been led to understand that you can't use nullable generics ie. T?). However this approach gnerates an error

Type parameter declaration must be an identifier not a type

If i don't use Object? though and just use Object or T i get this error instead

Cannot convert null to type parameter 'T' because it could be a non-nullable value type. Consider using 'default(T)' instead.

What's the correct syntax and approach to use in this case?

Darkreaper
  • 21
  • 4
  • There are some possible solutions here: http://stackoverflow.com/questions/19831157/c-sharp-generic-type-constraint-for-everything-nullable – Peter Kalmakis Sep 04 '15 at 21:27

3 Answers3

3

If you want to restrict your generic type to objects only - i.e. no structs or simple types - you can add the where clause

public class CubicMatrix<T> where T : class

These means that T can only be a class.

Kirk Broadhurst
  • 27,836
  • 16
  • 104
  • 169
  • That's not true, structs satisfy the [`new()`](https://msdn.microsoft.com/en-us/library/sd2w2ew5.aspx) constraint. [Compiling example](http://ideone.com/hf56HY). You're probably looking for the `class` constraint. – 31eee384 Sep 04 '15 at 22:15
  • @31eee384 you're right - thanks, I've updated the answer. – Kirk Broadhurst Sep 04 '15 at 22:18
  • 1
    Using an object constraint generates the error _Constraint cannot be special class 'object'_ But using where T : class constraint works. Thanks for the help – Darkreaper Sep 05 '15 at 23:24
  • @Darkreaper thanks - updated. My C# must be a little rusty. – Kirk Broadhurst Sep 05 '15 at 23:30
1

I think you want to use the generic parameter T. You're making a simple container class, so allowing any generic parameter makes sense, whether it's nullable or not. To fix the error, just do what it says and use default(T) instead of null.

The error is because T could be a class or a struct, and structs can't be null. Therefore assigning a variable with type T to null is invalid. default(T) is null when T is a class and default values when T is a struct.

31eee384
  • 2,748
  • 2
  • 18
  • 27
1

When returning default(T) instead (as the error you are getting suggests), reference types will return null, numeric types will return 0, your custom classes will return null and nullables will return System.Nullable<T>. More about this in default Keyword in Generic Code (C# Programming Guide) on MSDN.

trashr0x
  • 6,457
  • 2
  • 29
  • 39