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.
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.
Can somebody please help me to write a DeepCopy routine for this matrix class I have ? I dont have a great deal of experience in C#.
public class Matrix<T>
{
private readonly T[][] _matrix;
private readonly int row;
private readonly int col;
public Matrix(int x, int y)
{
_matrix = new T[x][];
row = x;
col = y;
for (int r = 0; r < x; r++)
{
_matrix[r] = new T[y];
}
}
}
Thanks in advance
The simplest way of deep copying would be using some kind of serializer (for instance BinaryFormatter), but this requires not only your type to be decorated as Serializable, but also the type T.
An example implementation of that could be:
[Serializable]
public class Matrix<T>
{
// ...
}
public static class Helper
{
public static T DeepCopy<T>(T obj)
{
using (var stream = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(stream, obj);
stream.Position = 0;
return (T) formatter.Deserialize(stream);
}
}
}
The issue here, is that you have no control over which type is supplied as generic type parameter. Without knowing more about which kind of types you wish to clone, an option might be to put a generic type constraint on T to only accept types that implement ICloneable.
In which case you could clone Matrix<T> like so:
public class Matrix<T> where T: ICloneable
{
// ... fields and ctor
public Matrix<T> DeepCopy()
{
var cloned = new Matrix<T>(row, col);
for (int x = 0; x < row; x++) {
for (int y = 0; y < col; y++) {
cloned._matrix[x][y] = (T)_matrix[x][y].Clone();
}
}
return cloned;
}
}
How to create dynamic incrementing variable using "for" loop in C#? like this:
track_1, track_2, track_3, track_4. so on.
You can't create dynamically-named variables. All you can do - it to create some collection or array, and operate with it.
I think the best class for you is generic List<>:
List<String> listWithDynamic = new List<String>();
for (int i = 1; i < limit; i +=1)
{
listWithDynamic.Add(string.Format("track_{0}", i));
...
}
Assuming you want strings:
for (int i = 1; i < limit; i +=1)
{
string track = string.Format("track_{0}", i);
...
}
But when you already have variables called track_1, track_2, track_3, track_4 you will need an array or List:
var tracks = new TrackType[] { track_1, track_2, track_3, track_4 } ;
for (int i = 0; i < tracks.length; i++)
{
var track = tracks[i]; // tracks[0] == track_1
...
}
Obvious Solution
for (var i = 0; i < 10; i++)
{
var track = string.Format("track_{0}", i);
}
Linq-Based Solution
foreach (var track in Enumerable.Range(0, 100).Select(x => string.Format("track_{0}", x)))
{
}
Operator-Based Solution This is somewhat hacky, but fun none-the-less.
for (var i = new Frob(0, "track_{0}"); i < 100; i++)
{
Console.WriteLine(i.ValueDescription);
}
struct Frob
{
public int Value { get; private set; }
public string ValueDescription { get; private set; }
private string _format;
public Frob(int value, string format)
: this()
{
Value = value;
ValueDescription = string.Format(format, value);
_format = format;
}
public static Frob operator ++(Frob value)
{
return new Frob(value.Value + 1, value._format);
}
public static Frob operator --(Frob value)
{
return new Frob(value.Value - 1, value._format);
}
public static implicit operator int(Frob value)
{
return value.Value;
}
public static implicit operator string(Frob value)
{
return value.ValueDescription;
}
public override bool Equals(object obj)
{
if (obj is Frob)
{
return ((Frob)obj).Value == Value;
}
else if (obj is string)
{
return ((string)obj) == ValueDescription;
}
else if (obj is int)
{
return ((int)obj) == Value;
}
else
{
return base.Equals(obj);
}
}
public override int GetHashCode()
{
return Value;
}
public override string ToString()
{
return ValueDescription;
}
}
don't know if I get your question, but I will try:
for(var i = 1; i < yourExclusiveUpperbound; i++)
{
var track = String.Format("$track_{0}", i);
// use track
}
or with some LINQ-Magic:
foreach(var track in Enumerate.Range(1, count)
.Select(i => String.Format("$track_{0}", i)))
{
// use track
}
Do as follow:
for (int i = 0; i < lenght; i ++)
{
any work do in loop
}
No, we can't create dynamically named variables in a loop. But, there are other elegant ways to address the problem instead of creating dynamically named variables.
One could be, create an array or list before the loop and store values in array / list items in the loop. You can access the array / list later anywhere in your code. If you know which variable you want to use (track_1, track_2, ...), you can simply access it from the array / list (tracks[1], tracks[2], ...).
List<String> tracks = new List<String>();
for (int i = 1; i < limit; i++)
{
Track track = new Track();
tracks.Add(track);
...
}
I'd like to create my own class extending array of ints. Is that possible? What I need is array of ints that can be added by "+" operator to another array (each element added to each), and compared by "==", so it could (hopefully) be used as a key in dictionary.
The thing is I don't want to implement whole IList interface to my new class, but only add those two operators to existing array class.
I'm trying to do something like this:
class MyArray : Array<int>
But it's not working that way obviously ;).
Sorry if I'm unclear but I'm searching solution for hours now...
UPDATE:
I tried something like this:
class Zmienne : IEquatable<Zmienne>
{
public int[] x;
public Zmienne(int ilosc)
{
x = new int[ilosc];
}
public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
{
return false;
}
return base.Equals((Zmienne)obj);
}
public bool Equals(Zmienne drugie)
{
if (x.Length != drugie.x.Length)
return false;
else
{
for (int i = 0; i < x.Length; i++)
{
if (x[i] != drugie.x[i])
return false;
}
}
return true;
}
public override int GetHashCode()
{
int hash = x[0].GetHashCode();
for (int i = 1; i < x.Length; i++)
hash = hash ^ x[i].GetHashCode();
return hash;
}
}
Then use it like this:
Zmienne tab1 = new Zmienne(2);
Zmienne tab2 = new Zmienne(2);
tab1.x[0] = 1;
tab1.x[1] = 1;
tab2.x[0] = 1;
tab2.x[1] = 1;
if (tab1 == tab2)
Console.WriteLine("Works!");
And no effect. I'm not good with interfaces and overriding methods unfortunately :(. As for reason I'm trying to do it. I have some equations like:
x1 + x2 = 0.45
x1 + x4 = 0.2
x2 + x4 = 0.11
There are a lot more of them, and I need to for example add first equation to second and search all others to find out if there is any that matches the combination of x'es resulting in that adding.
Maybe I'm going in totally wrong direction?
For a single type, it is pretty easy to encapsulate, as below. Note that as a key you want to make it immutable too. If you want to use generics, it gets harder (ask for more info):
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
static class Program {
static void Main() {
MyVector x = new MyVector(1, 2, 3), y = new MyVector(1, 2, 3),
z = new MyVector(4,5,6);
Console.WriteLine(x == y); // true
Console.WriteLine(x == z); // false
Console.WriteLine(object.Equals(x, y)); // true
Console.WriteLine(object.Equals(x, z)); // false
var comparer = EqualityComparer<MyVector>.Default;
Console.WriteLine(comparer.GetHashCode(x)); // should match y
Console.WriteLine(comparer.GetHashCode(y)); // should match x
Console.WriteLine(comparer.GetHashCode(z)); // *probably* different
Console.WriteLine(comparer.Equals(x,y)); // true
Console.WriteLine(comparer.Equals(x,z)); // false
MyVector sum = x + z;
Console.WriteLine(sum);
}
}
public sealed class MyVector : IEquatable<MyVector>, IEnumerable<int> {
private readonly int[] data;
public int this[int index] {
get { return data[index]; }
}
public MyVector(params int[] data) {
if (data == null) throw new ArgumentNullException("data");
this.data = (int[])data.Clone();
}
private int? hash;
public override int GetHashCode() {
if (hash == null) {
int result = 13;
for (int i = 0; i < data.Length; i++) {
result = (result * 7) + data[i];
}
hash = result;
}
return hash.GetValueOrDefault();
}
public int Length { get { return data.Length; } }
public IEnumerator<int> GetEnumerator() {
for (int i = 0; i < data.Length; i++) {
yield return data[i];
}
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
public override bool Equals(object obj)
{
return this == (obj as MyVector);
}
public bool Equals(MyVector obj) {
return this == obj;
}
public override string ToString() {
StringBuilder sb = new StringBuilder("[");
if (data.Length > 0) sb.Append(data[0]);
for (int i = 1; i < data.Length; i++) {
sb.Append(',').Append(data[i]);
}
sb.Append(']');
return sb.ToString();
}
public static bool operator ==(MyVector x, MyVector y) {
if(ReferenceEquals(x,y)) return true;
if(ReferenceEquals(x,null) || ReferenceEquals(y,null)) return false;
if (x.hash.HasValue && y.hash.HasValue && // exploit known different hash
x.hash.GetValueOrDefault() != y.hash.GetValueOrDefault()) return false;
int[] xdata = x.data, ydata = y.data;
if(xdata.Length != ydata.Length) return false;
for(int i = 0 ; i < xdata.Length ; i++) {
if(xdata[i] != ydata[i]) return false;
}
return true;
}
public static bool operator != (MyVector x, MyVector y) {
return !(x==y);
}
public static MyVector operator +(MyVector x, MyVector y) {
if(x==null || y == null) throw new ArgumentNullException();
int[] xdata = x.data, ydata = y.data;
if(xdata.Length != ydata.Length) throw new InvalidOperationException("Length mismatch");
int[] result = new int[xdata.Length];
for(int i = 0 ; i < xdata.Length ; i++) {
result[i] = xdata[i] + ydata[i];
}
return new MyVector(result);
}
}
Its not permitted to extend the array class, see the reference: http://msdn.microsoft.com/en-us/library/system.array.aspx
You could either implement IList (which has the basic methods), or encapsulate an Array in your class and provide conversion operators.
Please let me know if you need more detail.
Can you not just use the List class? This already does what you want via the AddRange method.
implement the ienumerable interface
I am trying to make an extension method that will shuffle the contents of a generic list collection regardless of its type however im not sure what to put in between the <..> as the parameter. do i put object? or Type? I would like to be able to use this on any List collection i have.
Thanks!
public static void Shuffle(this List<???????> source)
{
Random rnd = new Random();
for (int i = 0; i < source.Count; i++)
{
int index = rnd.Next(0, source.Count);
object o = source[0];
source.RemoveAt(0);
source.Insert(index, o);
}
}
You need to make it a generic method:
public static void Shuffle<T>(this List<T> source)
{
Random rnd = new Random();
for (int i = 0; i < source.Count; i++)
{
int index = rnd.Next(0, source.Count);
T o = source[0];
source.RemoveAt(0);
source.Insert(index, o);
}
}
That will allow it to work with any List<T>.
You just make your own method generic:
public static void Shuffle<T>(this List<T> source)
Slightly off-topic, but a Fisher-Yates shuffle will have less bias and better performance than your method:
public static void ShuffleInPlace<T>(this IList<T> source)
{
if (source == null) throw new ArgumentNullException("source");
var rng = new Random();
for (int i = 0; i < source.Count - 1; i++)
{
int j = rng.Next(i, source.Count);
T temp = source[j];
source[j] = source[i];
source[i] = temp;
}
}
I Think this solution faster to process, because you will get your itens randomly and your collection position will be preserved to future use.
namespace MyNamespace
{
public static class MyExtensions
{
public static T GetRandom<T>(this List<T> source)
{
Random rnd = new Random();
int index = rnd.Next(0, source.Count);
T o = source[index];
return o;
}
}
}
Steps:
Create your Static Class to Identify your extensions
Create you Extension Method (must be static)
Process your data.