Related
Not sure if it's possible, but I'd like to be able to populate a List<T> based on what T is. Presently, I have something like this (please forgive the generic names - it's for testing purposes):
public static class CollectionsClass
{
List<Object1> list1 = new List<Object1>();
List<Object2> list2 = new List<Object2>();
List<Object3> list3 = new List<Object3>();
}
public static class ActionClass
{
public static void PopulateCollections()
{
Populate(CollectionsClass.list1, 0, 10);
Populate(CollectionsClass.list2, 20, 50);
Populate(CollectionsClass.list3, 30, 100);
}
private static void Populate(dynamic list, int minLimit, int maxLimit)
{
var rnd = new Random();
int rndNum = rnd.Next(minLimit, maxLimit);
for (int i = 0; i < rndNum; i++)
{
if (list.GetType() == typeof(List<Object1>))
{
list.Add(new Object1());
}
else if (list.GetType() == typeof(List<Object2>))
{
list.Add(new Object2());
}
else if (list.GetType() == typeof(List<Object3>))
{
list.Add(new Object3());
}
else
{
// put out an error
}
}
}
}
While that code works, I'd like to shrink it by doing something like:
list.Add(new list.ObjectType());
I've been messing around with reflections and getting types all day, but I just can't seem to figure this one out.
Don't use dynamics, use generics:
static void Populate<T>(List<T> list, ...) where T: new()
{
...
for (int i=0; i<rndNum; i++)
list.Add(new T());
}
Since you're already using dynamic, you should be able to add method to handle this:
private static void AddToList<T>(List<T> list) where T : new()
{
list.Add(new T());
}
Given that, you can write:
private static void Populate(dynamic list, int minLimit, int maxLimit)
{
var rnd = new Random();
int rndNum = rnd.Next(minLimit, maxLimit);
for (int i = 0; i < rndNum; i++)
{
AddToList(list);
}
}
Try to use generic method:
public static class CollectionsClass
{
public static List<Object1> list1 = new List<Object1>();
public static List<Object2> list2 = new List<Object2>();
public static List<Object3> list3 = new List<Object3>();
}
public static class ActionClass
{
public static void PopulateCollections()
{
Populate(CollectionsClass.list1, 0, 10);
Populate(CollectionsClass.list2, 20, 50);
Populate(CollectionsClass.list3, 30, 100);
}
private static void Populate<T>(List<T> list, int minLimit, int maxLimit)
where T : new()
{
var rnd = new Random();
int rndNum = rnd.Next(minLimit, maxLimit);
for (int i = 0; i < rndNum; i++)
{
list.Add(new T());
}
}
}
Sounds like you want a combination of generics and reflection.
First of all make it generic:
void Populate<T>(List<T> mylist)
Now you know the type of your list: it's T.
All that is left is looping and creating instances of a particular type T. For this you can use Activator.CreateInstance:
for(int i = 0; i < 5; i++){
mylist.Add((T) Activator.CreateInstance(typeof(T)));
}
With this sample code:
void Main()
{
Populate<Type1>(new List<Type1>());
Populate<Type2>(new List<Type2>());
}
void Populate<T>(List<T> mylist){
for(int i = 0; i < 5; i++){
mylist.Add((T) Activator.CreateInstance(typeof(T)));
}
foreach(var item in mylist){
Console.WriteLine (item);
}
}
class Type1 { }
class Type2 { }
class Type3 { }
You get this output:
This will rely on reflection to create an instance of your object any assumes there is a public non-parameter constructor available (otherwise an exception will be thrown from the Activator).
This is not quite desirable behaviour and I realized it as soon as I saw the other answers that use the where T : new() constraint in their generic function: use this method over mine.
I'll still leave it in here for completeness though (at the very least it demonstrates a possible trap).
Use factory to extract the creation logic, reflection to get the correct type, and Activator to get the instance.
public static class TFactory
{
public static T Getmplementation<T>()
{
var typeName = typeof(T).Name;
var type = Type.GetType(typeName);
if (type != null)
return Activator.CreateInstance(type) as T;
else
throw new NotImplementedException(typeName);
}
}
Then,
List.Add(TFactory.GetImplmentation<'T>());
You can use a generic with a new constraint to achieve this:
private static void PopulateList<T>(List<T> list, int minLimit, int maxLimit)
where T : new()
{
var rnd = new Random();
int rndNum = rnd.Next(minLimit, maxLimit);
for (int i = 0; i < rndNum; i++)
{
list.Add(new T());
}
}
The constraint is that the type T must provide a default constructor. If you want to add items to a List, you do not need the dynamic keyword as you can specify List<T> as parameter type directly.
If you cannot add a default constructor, you can also provide a creator function:
private static void PopulateList<T>(List<T> list, Func<int, T> creatorFunc,
int minLimit, int maxLimit)
{
var rnd = new Random();
int rndNum = rnd.Next(minLimit, maxLimit);
for (int i = 0; i < rndNum; i++)
{
list.Add(creatorFunc(i));
}
}
You call the method like this:
var lst = new List<MyObjectType>();
PopulateList<MyObjectType>(lst, x => new MyObjectType(x), 1, 7);
In this sample, the value of i is provided to the creatorFunc that returns a new object of type MyObjectType.
I need an int array, from an int value.
The int value 123456 converts to int[] {1,2,3,4,5,6}.
Is there any better solution than this:
using System.Diagnostics;
namespace test
{
#if DEBUG
[DebuggerDisplay("{GetDebuggerDisplay()}")]
#endif
public class IntArray
{
#if DEBUG
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
#endif
private int _value;
#if DEBUG
[DebuggerBrowsableAttribute(DebuggerBrowsableState.Never)]
#endif
private int[] _valueArray;
public IntArray(int intValue)
{
Value = intValue;
}
public int Value
{
get { return _value; }
set
{
_value = value;
_valueArray = null;
_valueArray = CreateIntArray(value);
}
}
public int[] Array
{
get { return _valueArray; }
}
private string GetDebuggerDisplay()
{
return string.Format("Value = {0}", Value);
}
private static int[] CreateIntArray(int value)
{
string s = value.ToString();
var intArray = new int[s.Length];
for (int i = 0; i < s.Length; i++)
intArray[i] = int.Parse(s[i].ToString());
return intArray;
}
}
}
Any help and criticism would be appreciated.
You can do as following using Linq. This is only the making of the array from the int value.
var arrayOfInts = myint.ToString().Select(i => int.Parse(i.ToString())).ToArray();
EDIT :
This can also be made as a extension method on int if you want to use this often.
public static class IntExtensions
{
public static int[] ToArray(this int i)
{
return i.ToString().Select(c => int.Parse(c.ToString())).ToArray();
}
}
Then you can use this extension by doing this :
var myArray = 123456.ToArray();
You may convert to int to String, later you can use LINQ to Convert each character to integer and then return an array of integers using .ToArray()
int a = 123456;
string tempA = a.ToString();
int[] temp = tempA.Select(r => Convert.ToInt32(r.ToString())).ToArray();
EDIT:
As per Styxxy comment:
int a = 123456;
int[] array = new int[a.ToString().Length];
int i = array.Length - 1;
while (a > 0)
{
array[i--] = a % 10;
a = a / 10;
}
Another approach:
public static int[] GetInts(this int value)
{
if (value == 0)
return new int[] { 0 };
else
{
int val = value;
List<int> values = new List<int>();
while (Math.Abs(val) >= 1)
{
values.Add(Math.Abs(val % 10));
val = val / 10;
}
values.Reverse();
return values.ToArray();
}
}
and use it:
int value = 123456;
int[] values = value.GetInts();
Edit: improved to work with negative numbers and zero
var res = 123456.ToString().Select(c => Int32.Parse(c.ToString())).ToArray();
Another way using char.GetNumericValue:
int[] ints = 123456.ToString().Select(c => (int)char.GetNumericValue(c)).ToArray();
or without Linq:
var chars = 123456.ToString();
int[] ints = new int[chars.Length];
for (int i = 0; i < chars.Length; i++)
ints[i] = (int)char.GetNumericValue(chars[i]);
As said in the comments, it is better to use basic arithmetic operations, rather than converting to a string, looping through a string and parsing strings to integers.
Here is an example (I made an extension method for an integer):
static class IntegerExtensions
{
public static int[] ToCypherArray(this int value)
{
var cyphers = new List<int>();
do
{
cyphers.Add(value % 10);
value = value / 10;
} while (value != 0);
cyphers.Reverse();
return cyphers.ToArray();
}
}
class Program
{
static void Main(string[] args)
{
int myNumber = 123456789;
int[] cypherArray = myNumber.ToCypherArray();
Array.ForEach(cypherArray, (i) => Console.WriteLine(i));
Console.ReadLine();
}
}
I am trying to initialize a newly created empty array by using a method. Example below.
This is the structure of the code that I want to create.
var v = exClass[5,5];
v.ExtensionMethodThatWillInitilize();
What I want ExtensionMethodThatWIllInitilize to do is following:
for(int y = 0 ; y < exClass.getLength(0); y++ ) {
for(int x = 0 ; x < exClass.getLength(1); x++ ) {
v[y,x] = new instanceObject();
}}
So I came up with below code...
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var oldEx = new ExClass[10, 10];
var newEx = oldEx.init();
}
}
public class ExClass
{
public string exString
public ExClass() {
exString = " I AM NEW! YES! ";
}
}
public static class tools
{
static public ExClass[,] init(this ExClass[,] start)
{
var newArray = new ExClass[start.GetLength(0), start.GetLength(1)];
for (int y = 0; y < start.GetLength(0); y++)
{
for (int x = 0; x < start.GetLength(1); x++)
{
newArray[y, x] = new ExClass();
}
}
return newArray;
}
}
Yet the problem is that I do not know how to modify my init method so that it can take any type of array and return corresponding array that had been initialize.
I tried to use generic type T but my lack of experience seems to fail.
Summery:
1) how do you come up with a method that will initialize an empty array in a single step.
2) how do you make sure that the method can initialize any type of array(assuming that the element in the array has a constructor that does not take any argument)
Generics do work. You need to declare your method as a generic type.
I have modified the above example as follows:
class Program
{
static void Main(string[] args)
{
var oldEx = new ExClass[10, 10];
var newEx = oldEx.init<ExClass>();
}
}
public class ExClass
{
public string exString = "I AM NEW";
}
public static class tools
{
static public T[,] init<T>(this T[,] start)
{
var newArray = new T[start.GetLength(0), start.GetLength(1)];
for (int y = 0; y < start.GetLength(0); y++)
{
for (int x = 0; x < start.GetLength(1); x++)
{
newArray[y, x] = Activator.CreateInstance<T>();
}
}
return newArray;
}
}
As an answer to your comment below:
class Program
{
static void Main(string[] args)
{
var oldEx = tools.init<ExClass>(10, 10);
}
}
public class ExClass
{
public string exString = "I AM NEW";
}
public static class tools
{
static public T[,] init<T>(int x,int y)
{
var newArray = new T[x, y];
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y; j++)
{
newArray[i, j] = Activator.CreateInstance<T>();
}
}
return newArray;
}
}
Check out this generic method, which uses the new generic constraint:
static public void Init<T>(this T[,] array) where T : new()
{
for (int y = 0; y < array.GetLength(0); y++)
{
for (int x = 0; x < array.GetLength(1); x++)
{
array[y, x] = new T();
}
}
}
The main differences from your code are:
1) The method is Init to specify a generic parameter, and there where T : new() constraint ensures that we can call new T();
2) Instead of returning a new, initialized array, I'm simply initializing the array in-place. Seems more logical. If you want, you can use your original version, but I don't understand why you'd need to.
Mostly it comes handy that C# delegates already store the object together with the member function. But is there a way, to store -- and pass as parameters -- only the member function itself, just as the good old pointer-to-member-function in C++?
In case the description is less than clear, I give a self-contained example. And, yes, in the example the insistence to pass around member functions is totally pointless, but I have more serious uses for this.
class Foo {
public int i { get; set; }
/* Can this be done?
public static int Apply (Foo obj, ???? method, int j) {
return obj.method (j);
}
*/
public static int ApplyHack (Foo obj, Func<int, int> method, int j) {
return (int) method.Method.Invoke (obj, new object [] { j });
}
public static readonly Foo _ = new Foo (); // dummy object for ApplyHack
public int Multiply (int j) {
return i * j;
}
public int Add (int j) {
return i + j;
}
}
class Program {
static void Main (string [] args) {
var foo = new Foo { i = 7 };
Console.Write ("{0}\n", Foo.ApplyHack (foo, Foo._.Multiply, 5));
Console.Write ("{0}\n", Foo.ApplyHack (foo, Foo._.Add, 5));
Console.ReadKey ();
}
}
You see, the only workaround I've found is rather ugly and probably slow.
What you want is something called an open instance delegate. I've written about them on my blog
Basically, you can create a delegate to an instance method without tying it to a particular instance, and specify the instance to use it on when you call it:
class Foo {
public int i { get; set; }
public int Multiply (int j) {
return i * j;
}
public int Add (int j) {
return i + j;
}
}
class Program {
static void Main (string [] args) {
Func<Foo, int, int> multiply = (Func<Foo, int, int>)Delegate.CreateDelegate(typeof(Func<Foo, int, int>), null, typeof(Foo).GetMethod("Multiply");
Func<Foo, int, int> add = (Func<Foo, int, int>)Delegate.CreateDelegate(typeof(Func<Foo, int, int>), null, typeof(Foo).GetMethod("Add");
var foo1 = new Foo { i = 7 };
var foo2 = new Foo { i = 8 };
Console.Write ("{0}\n", multiply(foo1, 5));
Console.Write ("{0}\n", add(foo1, 5));
Console.Write ("{0}\n", multiply(foo2, 5));
Console.Write ("{0}\n", add(foo2, 5));
Console.ReadKey ();
}
}
Taking your existing code:
public static int ApplyHack (Foo obj, Func<int, int> method, int j) {
return (int) method.Method.Invoke (obj, new object [] { j });
}
You could do something like this:
public static int ApplyHack (Foo obj, Func<int, int> method, int j) {
var func = (Func<int,int>)Delegate.CreateDelegate(typeof(Func<int,int>), obj, method.Method);
return func(j);
}
This will create a new delegate around the method and the new object. To take your first example:
public static int Apply (Foo obj, ???? method, int j) {
return obj.method (j);
}
The type you are looking for is System.Reflection.MethodInfo and it would look like this:
public static int Apply (Foo obj, MethodInfo method, int j) {
var func = (Func<int,int>)Delegate.CreateDelegate(typeof(Func<int,int>), obj, method);
return func(i);
}
Note that while you are allocating delegates for each invocation, I believe this will still be faster than using reflection, since you do not have to box function input/output, nor store it in object[] arrays.
Assuming you're using C# 2.0 or above, and have access to anonymous delegates, you can do it very simply by wrapping the function in an anonymous delegate at the point of storage:
class Foo
{
public Foo(int v)
{
this.v = v;
}
int v;
public int Multiply(int x)
{
return v * x;
}
public int Add(int x)
{
return v+x;
}
delegate int NewFunctionPointer(Foo, int);
delegate int OldDelegateStyle(int);
static void Example()
{
Foo f = new Foo(2);
Foo f2 = new Foo(3);
// instead of this, which binds an instance
OldDelegateStyle oldMul = f.Multiply;
// You have to use this
NewFunctionPointer mul = delegate(Foo f, int x) { return f.Multiply(x); }
NewFunctionPointer add = delegate(Foo f, int x) { return f.Add(x); }
// But can now do this
mul(f, 4); // = 8
add(f2, 1); // = 3
}
}
If you're okay with passing the this reference as a parameter, why not just use static methods?
class Foo {
public int i;
public static int ApplyHack(Foo foo, Func<Foo, int, int> method, int j) {
return method(foo, j);
}
public static int Multiply(Foo foo, int j) {
return foo.i * j;
}
}
Console.Write("{0}\n", Foo.ApplyHack(foo, Foo.Multiply, 5));
This mainly affects how you construct the Foo object, without changing how you use it. It also doesn't prevent you from having a non-static int Multiply(int) method.
You could retrieve and reuse the MethodInfo for the method or just use the name and extract the method at runtime.
public static int ApplyHack (Foo obj, string methodName, int j)
{
var method = typeof(Foo).GetMethod(methodName);
return (int) method.Invoke (obj, new object [] { j });
}
I'd be very careful that this was actually necessary as it seems like a code smell to me.
You can do it that way
class Foo
{
public int i { get; set; }
public static int Apply(Foo obj, Func<int, int, int> method, int j)
{
return method(j, obj.i);
}
public static int Multiply(int j, int i)
{
return i * j;
}
public static int Add(int j, int i)
{
return i + j;
}
}
static void Main(string[] args)
{
var foo = new Foo { i = 7 };
Console.Write("{0}\n", Foo.Apply(foo, Foo.Multiply, 5));
Console.Write("{0}\n", Foo.Apply(foo, Foo.Add, 5));
Console.ReadKey();
}
I think you can do this easily with this if I understand correctly:
public static int Apply(Func<int, int> method, int j)
{
return (int)method.Method.Invoke(method.Target, new object[] { j });
}
and call it like this:
Console.Write("{0}\n", Foo.Apply(foo.Multiply, 5));
I'm pretty darn new to C# and I can't figure out how to express something pretty simple.
I have a 3D array that is private.
I have no problem with the function that exposes the contents to read:
public Terrain Tile(int x, int y, int z) { return ....
but I also want an internal function that provides read/write access with a coordinate transformation.
There seems to be no way to specify a setter.
Looking at Microsoft's site it appears that it wants []'s instead of ()'s but that results in the compiler thinking it's an array definition and of course it barfs all over the place. Googling elsewhere I find plenty of people trying to modify a field of something returning a reference type which of course fails but this array is full of enums, not reference types.
Of course I can write a SetTile(x, y, z, terrain) function but being able to access it as an array is so much more clear & elegant, yet it appears to be impossible.
You can define a 'view' class with an indexer which is basically a property with arguments:
private Terrain[,,] rawArray = ...;
private View transformedArray = new View(rawArray);
private class View
{
private Terrain[,,] array;
public View(Terrain[,,] array)
{
this.array = array;
}
public Terrain this[int x, int y, int z]
{
get { ... }
set
{
this.array[2*x, 3*z, -y] = value;
}
}
}
Here's one option:
private Terrain[,,] rawArray = ...;
private View view = new View(rawArray);
private class View
{
private class TransformedView
{
private Terrain[,,] array;
public TransformedView(Terrain[,,] array)
{
this.array = array;
}
public Terrain this[int x, int y, int z]
{
get { ... }
set
{
this.array[2*x, 3*z, -y] = value;
}
}
}
private Terrain[,,] array;
public readonly TransformedView Transformed;
public View(Terrain[,,] array)
{
this.array = array;
Transformed = new TransformedView(array);
}
public Terrain this[int x, int y, int z]
{
get { ... }
set
{
this.array[x, z, y] = value;
}
}
}
To extend on dtb's answer, I wrote the following transform class:
public class Transform<T, K>
{
Func<K, T> _getFunc1;
Func<K, K, T> _getFunc2;
Func<K, K, K, T> _getFunc3;
Action<K, T> _setFunc1;
Action<K, K, T> _setFunc2;
Action<K, K, K, T> _setFunc3;
public T this[K k1]
{
get
{
if (_getFunc1 == null) throw new ArgumentException();
return _getFunc1(k1);
}
set
{
if (_getFunc1 == null) throw new ArgumentException();
_setFunc1(k1, value);
}
}
public T this[K k1, K k2]
{
get
{
if (_getFunc2 == null) throw new ArgumentException();
return _getFunc2(k1, k2);
}
set
{
if (_getFunc2 == null) throw new ArgumentException();
_setFunc2(k1, k2, value);
}
}
public T this[K k1, K k2, K k3]
{
get
{
if (_getFunc3 == null) throw new ArgumentException();
return _getFunc3(k1, k2, k3);
}
set
{
if (_getFunc3 == null) throw new ArgumentException();
_setFunc3(k1, k2, k3, value);
}
}
public Transform(Func<K, T> getFunc) { this._getFunc1 = getFunc; }
public Transform(Func<K, T> getFunc, Action<K, T> setFunc)
: this(getFunc)
{
this._setFunc1 = setFunc;
}
public Transform(Func<K, K, T> getFunc) { this._getFunc2 = getFunc; }
public Transform(Func<K, K, T> getFunc, Action<K, K, T> setFunc)
: this(getFunc)
{
this._setFunc2 = setFunc;
}
public Transform(Func<K, K, K, T> getFunc) { this._getFunc3 = getFunc; }
public Transform(Func<K, K, K, T> getFunc, Action<K, K, K, T> setFunc)
: this(getFunc)
{
this._setFunc3 = setFunc;
}
}
Allowing you to create sample classes like the following:
class TransformUser
{
int[, ,] _array = new int[4, 4, 4];
public Transform<int, int> Normal;
public Transform<int, int> Transformed;
public TransformUser()
{
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
for (int k = 0; k < 4; k++)
_array[i, j, k] = i * j * k;
Normal = new Transform<int, int>((x, y, z) => _array[x, y, z]);
Transformed = new Transform<int, int>((x, y, z) => _array[x, y / 2, z]);
}
}
With a use like the following:
TransformUser tu = new TransformUser();
Console.WriteLine(tu.Normal[2, 3, 2]);
Console.WriteLine(tu. Transformed[2, 3, 2]);