Creating a universal array at runtime

Is there a way in C # to do something like this:

public void Foo<T>() { T[] arr = Goo() as T[]; } 

Where does Goo return object[] using reflection or something else?

+4
source share
2 answers

You can use LINQ:

 public void Foo<T>() { T[] arr = Goo().OfType<T>().ToArray(); } 

In your example, you drop object[] in T[] , which will also work if the two types are exactly the same:

 public void Foo<T>() { T[] arr = Goo() as T[]; if (arr != null) { // use the array } } 

For example, this will work in the following case:

 public object[] Goo() { return new string[] { "a", "b" }; } 

and then calling foo like this:

 Foo<string>(); 
+4
source

Perhaps the simplest and most reliable approach is to copy the array by doing the cast by by item action:

 public void Foo<T>() { T[] arr = Array.ConvertAll(Goo(), x => (T)x); } 

This is " unbox.any ", which means (for JIT):

  • do a castclass (i.e. checking the persistence type) if T turns out to be a reference type
  • run unbox if T turns out to be a type value

Arrays of reference types are covariant, which means that a T[] can be represented as object[] . Because of this, there is a chance that the result of Goo() is actually T[] . We can also test this:

 public T[] Foo<T>() { var tmp = Goo(); T[] arr = tmp as T[]; if(arr == null && tmp != null) { arr = Array.ConvertAll(Goo(), x => (T)x); } return arr; } 

One of the irritants of this, however, is that we now have different semantics - in some cases it is the same array, in some cases it is copied. This can be problematic if we mutate the array.

0
source

Source: https://habr.com/ru/post/1435844/


All Articles