Question

The example below shows the intent. The example is iterating through an array of Objects, and creating an array with the same Types loaded with default values. The values themselves do not need to be copied from one list to the next. This is sort of a "Type Clone" of the list.

The code below produces the following error for the Activator:

"System.Int32 is not a GenericTypeDefinition. MakeGenericType may only be called on a type for which Type.IsGenericTypeDefinition is true."

The details of Activator, CreateInstance, and MakeGenericType are still a little confusing to me.

How can I change the code to avoid the error ?

Any suggestions would be appreciated.

    private void Test()
    {
        object[] a = new object[] {100, "Text", new clsMyClass()};
        object[] b = new object[a.Length];

        for (int i = 0; i < a.Length; i++)
        {
            b[i] = Activator.CreateInstance(a[i].GetType().MakeGenericType());
        }

        for (int i = 0; i < b.Length; i++)
        {
            Console.WriteLine(b[i].GetType().ToString());
        }
    }

The expected output would be:

  • System.Int32
  • System.String
  • MyNamespace.clsMyClass

The resulting values would be:

  • b[0] = 0
  • b[1] = ""
  • b[2] = new clsMyClass
Was it helpful?

Solution

remove MakeGenericType() and it will start to work, use this

b[i] = Activator.CreateInstance(a[i].GetType());

MakeGenericType is for Substituting generic parameters with defined ones. As example if your array would contain List<T>, call of a[i].GetType().MakeGenericType(typeof(int)) will return type List<int>.

In your case I don't see any generic type, so I wonder why you use it

Also note that calling Activator.CreateInstance like so will work only if type have parameterless constructor, which is not true for example in case of string. You can handle string case like this

for (int i = 0; i < a.Length; i++)
{
   var oType = a[i].GetType();
   if (oType == typeof(string)) 
       b[i] = string.Empty; //or may be null 
   else
       b[i] = Activator.CreateInstance(oType);
}

Something simular should be done for all types without parameterless constructor. Activator.CreateInstance(type, parameters...) can do the job. You can use reflection to investigate type constructor paramaters if needed

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top