How do I convert array of known type, for instance, decimal to array of dynamic - decimal[] to dynamic[]`?
I can do this manually, but I wonder whether there is something more sophisticated?
decimal[] decArray = someMethodReturnsDecimalArr();
// now conversion is needed
dynamic[] res = new dynamic[decArray.Count()];
for (var i = 0; i < res.Count(); i++)
{
res[i] = boundaries[i];
}
return res;
Why do I need this?
First, I really need this! I know that if the code would be written from scratch and by me, maybe I would use generics or something like that. But I cannot change that part of code that returns dynamic[].
So, there is class with dynamic[] properties:
public class Info
{
public dynamic[] Points { get; set; }
...
}
Based on different complicated criterias sometimes Points are decimal, sometimes DateTimes or there are also multiple other possibilities. This is based on data coming from database and also from UI.
This is not my design and I cannot changed it.
There is methodX that returns Info class.
My part is implement methods for some specific calculations and these methods return decimal[] or other types. Later I have to convert to dynamic[] so it would work with already existing methods.
decimal[] decArray = someMethodReturnsDecimalArr();
or
double[] doubleArray = someMethodReturnsDoubleArr();
And all these arrays have to be set to Points.
(I tried to simplify description here).
Use LINQ:
dynamic[] res = decArray.Cast<dynamic>().ToArray();
Use linq, method Cast
var res = decArray.Cast<dynamic>();
Related
I am developing a software that takes realtime-data and extracts a number of features from that depending on user input. Each available feature consists of one method that takes an array of doubles and return the wanted feature, such as this one for the MeanAbsoluteValue:
public static class MeanAbsoluteValue{
public static double Calculate(double[] data){
return data.Sum(s => Math.Abs(s)) / data.Length;
}
}
Since each of the features only has the one Calculate method I was thinking of trying to rewrite them so that they can be collected and chosen from that Collection.
I have tried writing an Interface for them to use, but since they are static this was not allowed.
Is there a way of doing this? And if so, could you point me in the right direction?
You can create an array of delegates constructed from the Calculate methods of these classes, like this:
Func<double[],double>[] array = new Func<double[],double>[] {
MeanAbsoluteValue.Calculate
, MeanValue.Calculate
, Deviation.Calculate
// ...and so on
};
Here is a demo on ideone.
Store delegates to your functions in a dictionary, and look them up by name
var methods = new Dictionary<string, Func<double[], double>>();
methods.Add("MeanAbsoluteValue", MeanAbsoluteValue.Calculate);
...
public double DoFunc(string name, double [] args)
{
var func = methods[name];
return func(args);
}
Just have a collection of Func...
var list = new List<Func<double[], double>(MeanAbsoluteValue.Calculate, Average.Calculate)
var accum = 0;
foreach(var func in list)
{
accum += func(new [] {1,3,4,});
}
Let's say a program like this:
class MyClass
{
public int Numbers;
public char Letters;
}
class Program
{
static void Main()
{
var mc = new MyClass[5];
for (var i = 0; i < 5; i++)
{
mc[i].Numbers = i + 1;
mc[i].Letters = (char) (i + 65);
}
}
}
Now, let's suppose an 'X' method that requires ALL the numbers contained in the object mc, in a separate array, that's sent as a parameter.
My first idea is a for, a new integers array, and copy one by one onto its respective position. But, what if the MyClass gets different, now it has strings and floats, and I wanna pull out the strings, now the for has to be completely redefined in its inside part to create the needed array for another 'X' method.
I know of cases where Linq helps a lot, for example, generics for Sum, Average, Count and another numeric functions, and of course, it's combination with lambda expressions.
I'm wondering if something similar exists to make the above arrays of MyClass (and anothers of course) in a faster-generic way?
If you want to use LINQ, you can do something like the following:
int [] numbers = mc.Select<MyClass, int>(m => mc.Number).ToArray();
To make it more generic than that, it gets a bit more complicated, and you may need reflection, or dynamic objects. A simple example with reflection would be:
private TValue[] ExtractFields<TClass, TValue>(TClass[] classObjs, string fieldName)
{
FieldInfo fInfo = typeof(TClass).GetField(fieldName, BindingFlags.Public | BindingFlags.Instance);
if (fInfo != null && fInfo.FieldType.Equals(typeof(TValue)))
return classObjs.Select<TClass, TValue>(c => (TValue)fInfo.GetValue(c)).ToArray();
else
throw new NotSupportedException("Unidentified field, or different field type");
}
And then just call it like:
int [] fields = ExtractField<MyClass, int>(mc, "Number");
If you are using C# 4.0, then you may use dynamic
class MyClass
{
public dynamic Numbers;
public char Letters;
}
EDIT: based on comments
I am not sure if this is what you want:
int[] arr = mc.Select(a => a.Numbers).ToArray<int>();
or without casting
int[] arr = mc.Select(a => a.Numbers).ToArray();
Why not just use Dictionary<int, char>, or if the data type is unknown then simply Dictionary<object, object>
If your goal is to generate a new array which is detached from the original array, but contains data copied from it, the most generic thing you could do would be to define a method like:
T my_array[]; // The array which holds the real things
U[] CopyAsConvertedArray<U>(Func<T,U> ConversionMethod);
That would allow one to generate a new array which extracts items from the original using any desired method.
I get from an input a group of double variables named: weight0, weight1...weight49.
I want to dynamically insert them into a double Array for easier manipulation.
But instead of calling each one like: Weights[0] = weight0...Weights[49] = weight49 I want to do it with a single loop.
Is there a way to do it?
No, basically - unless you mean at the same time that you create the array:
var weights = new[] {weight0, weight1, weight2, ... , weight48, weight49};
Personally, I'd be tempted to get rid of the 50 variables, and use the array from the outset, but that may not be possible in all cases.
you could use reflection to determine the index of the array from the variable names but this is far from efficient. See this post for details.
I would try to do it with a KeyValuePair- Listobject
// sample data
var weight = 1.00;
// create a list
var tmp = new List<KeyValuePair<string,object>>();
// Here you can add your variables
tmp.Add(new KeyValuePair<string,object>("weights" + tmp.Count.ToString()
, weight));
// If needed convert to array
var weights = tmp.ToArray();
// get the information out of the array
var weightValue = weights[0].Value;
var weightKey = weights[0].Key;
I think this will give you all the options, you might need for the array. Give it a try.
I'm putting this up because you can do it - so long as these variables are actually fields/properties. Whether you should is another matter - this solution, while reusable, is slow (needs delegate caching) and I have to say I agree with Marc Gravell - consider using an array throughout if you can.
If the variables are properties then it needs changing. Also if you need to write the array back to the variables in one shot (because this solution generates an array with copies of all the doubles, I wouldn't consider creating an object array with boxed doubles), that requires another method...
So here goes. First a holy wall of code/extension method:
//paste this as a direct child of a namespace (not a nested class)
public static class SO8877853Extensions
{
public static TArray[] FieldsToArray<TObj, TArray>(this TObj o,string fieldPrefix)
{
if(string.IsNullOrWhiteSpace(fieldPrefix))
throw new ArgumentException("fieldPrefix must not null/empty/whitespace",
"fieldPrefix");
//I've done this slightly more expanded than it really needs to be...
var fields = typeof(TObj).GetFields(System.Reflection.BindingFlags.Instance
| System.Reflection.BindingFlags.Public
| System.Reflection.BindingFlags.NonPublic)
.Where(f =>f.Name.StartsWith(fieldPrefix) && f.FieldType.Equals(typeof(TArray)))
.Select(f =>new{ Field = f, OrdinalStr = f.Name.Substring(fieldPrefix.Length)})
.Where(f => { int unused; return int.TryParse(f.OrdinalStr, out unused);})
.Select(f => new { Field = f.Field, Ordinal = int.Parse(f.OrdinalStr) })
.OrderBy(f => f.Ordinal).ToArray();
//doesn't handle ordinal gaps e.g. 0,1,2,7
if(fields.Length == 0)
throw new ArgumentException(
string.Format("No fields found with the prefix {0}",
fieldPrefix),
"fieldPrefix");
//could instead bake the 'o' reference as a constant - but if
//you are caching the delegate, it makes it non-reusable.
ParameterExpression pThis = Expression.Parameter(o.GetType());
//generates a dynamic new double[] { var0, var1 ... } expression
var lambda = Expression.Lambda<Func<TObj, TArray[]>>(
Expression.NewArrayInit(typeof(TArray),
fields.Select(f => Expression.Field(pThis, f.Field))), pThis);
//you could cache this delegate here by typeof(TObj),
//fieldPrefix and typeof(TArray) in a Dictionary/ConcurrentDictionary
return lambda.Compile()(o);
}
}
The extension method above will work on any type. It's generic over both the instance type and desired array type to simplify the creation of the lambda in code - it doesn't have to be generic though.
You pass in the name prefix for a group of fields - in your case "weight" - it then searches all the public and private instance fields for those with that prefix that also have a suffix which can be parsed into an integer. It then orders those fields based on that ordinal. It does not check for gaps in the ordinal list - so a type with weight0 and weight2 would work, but would only create a two-element array.
Then it bakes a dynamic piece of code using Expression trees, compiles it (at this point, as mentioned in the code, it would be good to cache the delegate against TObj and TArray for future use) and then executes it, returning the result.
Now add this to a test class in a standard unit test project:
private class SO8877853
{
private double field0 = 1.0;
private double field1 = -5.0;
private double field2 = 10.0;
public double[] AsArray()
{
//it would be nice not to have to pass both type names here - that
//can be achieved by making the extension method pass out the array
//via an 'out TArray[]' instead.
return this.FieldsToArray<SO8877853, double>("field");
}
}
[TestMethod]
public void TestThatItWorks()
{
var asArray = new SO8877853().AsArray();
Assert.IsTrue(new[] { 1.0, -5.0, 10.0 }.SequenceEqual(asArray));
}
Like I say - I'm not condoning doing this, nor am I expecting any +1s for it - but I'm a sucker for a challenge :)
I am planning to rewrite my Python Tile Engine in C#. It uses a list of all the game objects and renders them on the screen. My problem is that unlike in Python where you can add almost anything to an array (e.g x = ["jj" , 1, 2.3, 'G', foo]) you can add only one type of objects
in a C# array (int[] x = {1,2,3};) . Are there any dynamic arrays (similar to the ArrayList() class) or something which allows you to pack different types into a single array? because all the game objects are individual classes.
Very simple—create an array of Object class and assign anything to the array.
Object[] ArrayOfObjects = new Object[] {1,"3"}
you can use an object array. strings, int, bool, and classes are all considered objects, but do realize that each object doesn't preserve what it once was, so you need to know that an object is actually a string, or a certain class. Then you can just cast the object into that class/data type.
Example:
List<object> stuff = new List<object>();
stuff.add("test");
stuff.add(35);
Console.WriteLine((string)stuff[0]);
Console.WriteLine((int)stuff[1]);
Though, C# is a strongly typed language, so I would recommend you embrace the language's differences. Maybe you should look at how you can refactor your engine to use strong typing, or look into other means to share the different classes, etc. I personally love the way C# does this, saves me a lot of time from having to worry about data types, etc. because C# will throw any casting (changing one data type to another) errors I have in my code before runtime.
Also, encase you didn't know, xna is C#'s game framework (didn't have it as a tag, so I assume you aren't using it).
You can write an abstract base class called GameObject, and make all gameObject Inherit it.
Edit:
public abstract class GameObject
{
public GameObject();
}
public class TileStuff : GameObject
{
public TileStuff()
{
}
}
public class MoreTileStuff : GameObject
{
public MoreTileStuff()
{
}
}
public class Game
{
static void Main(string[] args)
{
GameObject[] arr = new GameObject[2];
arr[0] = new TileStuff();
arr[1] = new MoreTileStuff();
}
}
C# has an ArrayList that allows you to mix types within an array, or you can use an object array, object[]:
var sr = new ArrayList() { 1, 2, "foo", 3.0 };
var sr2 = new object[] { 1, 2, "foo", 3.0 };
In c# we use an object[] array to store different types of data in each element location.
object[] array1 = new object[5];
//
// - Put an empty object in the object array.
// - Put various object types in the array.
// - Put string literal in the array.
// - Put an integer constant in the array.
// - Put the null literal in the array.
//
array1[0] = new object();
array1[1] = new StringBuilder("Initialized");
array1[2] = "String literal";
array1[3] = 3;
array1[4] = null;
You can use object[] (an object array), but it would be more flexible to use List<object>. It satisfies your requirement that any kind of object can be added to it, and like an array, it can be accessed through a numeric index.
The advantage of using a List is you don't need to know how items it will hold when you create it. It can grow and shrink dynamically. Also, it has a richer API for manipulating the items it contains.
Here is how you can do it
Use List<object> (as everything is derived from object in C#):
var list = new List<object>();
list.Add(123);
list.Add("Hello World");
Also dynamic might work for you (and your python background)
var list = new List<dynamic>();
list.Add(123);
list.Add(new
{
Name = "Lorem Ipsum"
});
If you wan't to use dynamic you really need to know what you're doing. Please read this MSDN article before you start.
But do you need it?
C# is a strongly-typed and very solid programming language. It is very flexible and great for building apps using object-oriented and functional paradigms. What you want to do may be acceptable for python, but looks pretty bad on C#. My recommendation is: use object oriented programming and try to build model for your problem. Never mix types together like you tried. One list is for a single data-type. Would you like to describe your problem in depth so that we can suggest you a better solution?
In C# 4 and later you can also use dynamic type.
dynamic[] inputArray = new dynamic[] { 0, 1, 2, "as", 0.2, 4, "t" };
Official docu
You can mix specific types doing the following:
(string, int)[] Cats = { ("Tom", 20), ("Fluffy", 30), ("Harry", 40), ("Fur Ball", 40) };
foreach (var cat in Cats)
{
Console.WriteLine(string.Join(", ", cat));
}
You have to declare your array with the datatype object:
object[] myArray = { };
myArray[0] = false;
myArray[1] = 1;
myArray[2] = "test";
You can use an array of object class and all it possible to add different types of object in array.
object[] array = new object[3];
array[0] = 1;
array[1] = "string";
array[3] = 183.54;
Today I've gone through what indexers are, but I am bit confused. Is there really a need for indexers? What are the advantages of using an indexer..... thanks in advance
I guess the simplest answer is to look at how you'd use (say) List<T> otherwise. Would you rather write:
string foo = list[10];
or
string foo = list.Get(10);
Likewise for dictionaries, would you rather use:
map["foo"] = "bar";
or
map.Put("foo", "bar");
?
Just like properties, there's no real need for them compared with just named methods following a convention... but they make code easier to understand, in my view - and that's one of the most important things a feature can do.
Indexers let you get a reference to an object in a collection without having to traverse the whole collections.
Say you have several thousands of objects, and you need the one before last. Instead of iterating over all of the items in the collection, you simply use the index of the object you want.
Indexers do no have to be integers, so you can use a string, for example, (though you can use any object, so long as the collection supports it) as an indexer - this lets you "name" objects in a collection for later retrieval, also quite useful.
I think zedo got closest to the real reason IMHO that they have added this feature. It's for convenience in the same way that we have properties.
The code is easer to type and easier to read, with a simple abstraction to help you understand.
For instance:
string[] array;
string value = array[0];
List<string> list;
string value = list[0]; //Abstracts the list lookup to a call similar to array.
Dictionary<string, int> map;
int value = map["KeyName"]; //Overloaded with string lookup.
Indexers allow you to reference your class in the same way as an array which is useful when creating a collection class, but giving a class array-like behavior can be useful in other situations as well, such as when dealing with a large file or abstracting a set of finite resources.
yes , they are very use of
you can use indexers to get the indexed object.
Taken from MSDN
Indexers are most frequently implemented in types whose primary purpose is to encapsulate an internal collection or array.
Full Story
for some reason, use indexer can let you create meaningful index to store or map your data. then you can get it from other side by the meaningful index.
using System;
/* Here is a simple program. I think this will help you to understand */
namespace Indexers
{
class Demo
{
int[] a = new int[10];
public int Lengths
{
get
{
return a.Length;
}
}
public int this[int index]
{
get
{
return a[index];
}
set
{
a[index] = value;
}
}
}
class Program
{
static void Main(string[] args)
{
Demo d = new Demo(); // Notice here, this is a simple object
//but you can use this like an array
for (int i = 0; i < d.Lengths; i++)
{
d[i] = i;
}
for (int i = 0; i < d.Lengths; i++)
{
Console.WriteLine(d[i]);
}
Console.ReadKey();
}
}
}
/*Output:
0
1
2
3
4
5
6
7
8
9
*/