How to Create an Instance of an Arbitrary Array Type at Runtime

How can I create an instance of an arbitrary Array type at runtime?

Use Array.CreateInstance.

How do I create a C# array using Reflection and only type info?

Just to add to Jon's answer. The reason attempt 1 fails is because there's no default constructor for Int32[]. You need to supply a length. If you use the overload, which takes an array of arguments it will work:

// attempt1 
object y1 = Activator.CreateInstance(t, new object[] { 1 }); // Length 1

Create empty array using reflection

Some types you have to trap and handle special, for your case you'd use:

if ( type.IsArray){
var o = Array.CreateInstance(type, size);
}

Programmatically Declare Array of Arbitrary Rank

Use Array.CreateInstance(Type, Int32[]) method to create an array of an arbitrary size.

But the problem, you will have after creating this array is: How do you efficiently access the elements of the array if you don't know its rank?

You may use myArray.GetValue(Int32[]) and myArray.SetValue(Object, Int32[]) but I assume the performance is no that good.

To sum up:

public static Array CreateArray(Array array)
{
// Gets the lengths and lower bounds of the input array
int[] lowerBounds = new int[array.Rank];
int[] lengths = new int[array.Rank];
for (int numDimension = 0; numDimension < array.Rank; numDimension++)
{
lowerBounds[numDimension] = array.GetLowerBound(numDimension);
lengths[numDimension] = array.GetLength(numDimension);
}

Type elementType = array.GetType().GetElementType(); // Gets the type of the elements in the input array

return Array.CreateInstance(elementType, lengths, lowerBounds); // Returns the new array
}

Update

I've done a little benchmark to compare performance of the array indexer and the GetValue, SetValue versions.

Here is the code I used:

const int size = 10000000;
object[] array1 = new object[size];
object[] array2 = new object[size];

Random random;
random = new Random(0);
for (int i = 0; i < size; i++)
{
array1[i] = random.Next();
array2[i] = random.Next();
}

Stopwatch stopwatch = new Stopwatch();

Console.ReadKey();
stopwatch.Restart();
for (int i = 0; i < size; i++)
array1[i] = array2[i];
stopwatch.Stop();
Console.WriteLine("Indexer method: {0}", stopwatch.Elapsed);

random = new Random(0);
for (int i = 0; i < size; i++)
{
array1[i] = random.Next();
array2[i] = random.Next();
}

Console.ReadKey();
stopwatch.Restart();
for (int i = 0; i < size; i++)
array1.SetValue(array2.GetValue(i), i);
stopwatch.Stop();
Console.WriteLine("Get/SetValue method: {0}", stopwatch.Elapsed);

The result are:

Indexer method: 0.014 s
Set/GetValue method: 1.33 s

The result are slightly different if I replace the int by object.

Indexer method: 0.05 s
Set/GetValue method: 0.54 s

This can be easily explained by the necessary boxing/unboxing when using integer with Set/GetValue.

How to generate array type using a given type?

To get type from its string name you can use Type.GetType method.

To get array type from item use Type.MakeArrayType instance method:

 string itemTypeName = "System.Int32";

Type itemType = Type.GetType(itemTypeName);

Console.WriteLine(itemType.MakeArrayType());

Instantiate an object with a runtime-determined type

There are several ways you can create an object of a certain type on the fly, one is:

// determine type here
var type = typeof(MyClass);

// create an object of the type
var obj = (MyClass)Activator.CreateInstance(type);

And you'll get an instance of MyClass in obj.

Another way is to use reflection:

// get type information
var type = typeof(MyClass);

// get public constructors
var ctors = type.GetConstructors(BindingFlags.Public);

// invoke the first public constructor with no parameters.
var obj = ctors[0].Invoke(new object[] { });

And from one of ConstructorInfo returned, you can "Invoke()" it with arguments and get back an instance of the class as if you've used a "new" operator.

How to create a new object instance from a Type

The Activator class within the root System namespace is pretty powerful.

There are a lot of overloads for passing parameters to the constructor and such. Check out the documentation at:

http://msdn.microsoft.com/en-us/library/system.activator.createinstance.aspx

or (new path)

https://learn.microsoft.com/en-us/dotnet/api/system.activator.createinstance

Here are some simple examples:

ObjectType instance = (ObjectType)Activator.CreateInstance(objectType);

ObjectType instance = (ObjectType)Activator.CreateInstance("MyAssembly","MyNamespace.ObjectType");

How to create Bounded instance based on runtime values?

I wrote a long answer about Hasochism's Matrix's Applicative instance, using finite sets as index types, but it's probably overkill for what you wanted, not to mention less efficient than the Array-based code in the blog post.

Your problem stems from the fact that various operations in the blog post's code assume that the Bounded instance for the matrix's index type is covering, in the sense that every value within the bounds will have a corresponding element in the matrix. The core assumption seems to be that the size of the matrix is known statically.

The simplest way to fix this would be to make an adjustment to the Matrix type, so that it carries its size around with it. You still have to do all your bounds checking dynamically, but I think that's a fairly good trade-off compared to the weightiness of the Hasochism approach.

-- Bounded as an explicit (minBound, maxBound) tuple
type Bounds i = (i, i)
data Matrix i e = Matrix { getBounds :: Bounds i, getMatrix :: Array (Edge i) e }

entireRange :: Ix i => Bounds i -> [i]
entireRange b = range b

matrix :: Ix i => Bounds i -> (Edge i -> e) -> Matrix i e
matrix bounds f = Matrix bounds $ listArray bounds $ map f $ entireRange bounds

This gets stuck, however, when you need to construct a matrix in a type class instance. You can't abstract instances over runtime values: the only thing valid to the left of the => in an instance declaration is another type class constraint. In a declaration like

instance Bounded i => Applicative (Matrix i) where
pure x = matrix (const x)
(<*>) = -- ...

we have no choice than to pass the bounds statically in an instance dictionary because the type of pure doesn't allow us to pass explicit configuration data. This restriction has its ups and downs, but right now it's a definite downer: the fix is to rip all of the classiness out of your code altogether.


Good news, though: you can emulate this explicit dictionary-passing style using the crazy reflection library, which does evil, magical things to push runtime values into typeclass dictionaries. It's scary stuff, but it does work, and it's safe.

It all happens in the reify and reflect combinators. reify takes a runtime value and a block of code with a constraint depending on the availability of that value and plugs them in to one another. Calls to reflect inside the block return the value that was passed to reify outside it.

needsAnInt :: Reifies s Int => Proxy s -> IO ()
needsAnInt p = print (reflect p + 1)

example1 :: IO ()
example1 = reify 3 (\p -> needsAnInt p) -- prints 4
example2 :: IO ()
example2 = reify 5 (\p -> needsAnInt p) -- prints 6

Take a moment to reflect (ha ha) on how weird this is. Usually there's only one class dictionary in scope for each type (overlapping instances notwithstanding). Proxy has only one value (data Proxy a = Proxy), so how can reflect tell two proxies apart, to return different values each time?

Anyway, what's the point of this? Instances can't depend on runtime values, but they can depend on other instances. reflection gives us the tools to turn a runtime value into an instance dictionary, so this allows us to build instances which depend dynamically on runtime values!

In this case, we're building an instance of Bounded. We need a newtype, to make an instance which doesn't overlap with any others:

-- in this case it's fine to just lift the Ix instance from the underlying type
newtype B s i = B i deriving (Eq, Ord, Ix)

Clearly B can be an instance of Bounded if i is - it can get minBound and maxBound from i's instance - but we want to get them from a Reifies context. In other words, the runtime value we'll be stuffing into the Reifies dictionary will be a pair of is.

instance Reifies s (i, i) => Bounded (B s i) where
minBound = B $ fst $ reflect (Proxy :: Proxy s)
maxBound = B $ snd $ reflect (Proxy :: Proxy s)

I'm using ScopedTypeVariables crucially to come up with Proxy values of the correct type.

Now you can write perfectly ordinary code which uses a Bounded context (even if that context arises due to some other instance), and invoke it with a dynamically built Bounded dictionary using reify.

entireRange :: (Ix i, Bounded i) => [i]
entireRange = range (minBound, maxBound)

example3 :: IO ()
example3 = reify (3, 6) myComputation
where myComputation :: forall s. Bounded (B s Int) => Proxy s -> IO ()
myComputation p = print $ map unB (entireRange :: [B s Int])

ghci> example3
[3,4,5,6]

Um, yeah. reflection can be tricky to use. At the end of the day, it's probably simpler just to not bother with classes.



Related Topics



Leave a reply



Submit