Make an array of classes - c#

I need to create an array of another class.
Example:
namespace std
{
public class Car
{
double number,id;
public Car()
{
// initializing my variables for example:
number = Random.nextdouble();
}
}
public class Factory
{
public Factory(int num)
{
Car[] arr = new Car(num);
}
}
}
The problem is I get this error:
'Car' does not contain a constructor that takes '1' arguments
I just need to have an array of Car in Factory class (the car variables are initialized with its constructor).

You've just used the wrong brackets. You always use square brackets for arrays and indexers. Round brackets are to invoke methods, constructors etc. You meant:
car[] arr = new car[num];
Note that conventionally .NET types are Pascal-cased, so your types should be Car and Factory rather than car and factory.
Also note that after creating the array, each element will be a null reference - so you shouldn't write:
// Bad code - will go bang!
Car[] cars = new Car[10];
cars[0].SomeMethod(0);
Instead:
// This will work:
Car[] cars = new Car[10];
cars[0] = new Car(); // Populate the first element with a reference to a Car object
cars[0].SomeMethod();

You need to use [] not () when you declaring an array or indexers.
car[] arr = new car[num];

If your requirements doesn't constrain to use only Array, you can use a typed list.
List<Car> = new List<Car>(num);
//num has to be the size of list, but a list size is dinamically increased.
The error in your code is that array should be initialized as follows:
public class factory
{
public factory(int num)
{
car[] arr = new car[num];
}
}
Regards,

using System;
namespace ConsoleApplication1
{
public class Car
{
public double number { get; set; }
public Car()
{
Random r = new Random();
number = r.NextDouble();// NextDouble isn't static and requires an instance
}
}
public class Factory
{
//declare Car[] outside of the constructor
public Car[] arr;
public Factory(int num)
{
arr = new Car[num];
}
}
class Program
{
static void Main(string[] args)
{
Factory f = new Factory(3);
f.arr[0] = new Car();
f.arr[1] = new Car();
f.arr[2] = new Car();
foreach (Car c in f.arr)
{
Console.WriteLine(c.number);
}
Console.Read();
}
}
}

Related

How do I get a List<T> property in a class via reflection in C#?

I have a class called Animals what contains two List<T>.
One is a list of bears, and one is a list of pinguins.
I can pretty trivially get the list of bears by just calling Bears on the animals variable - but how do I get it via reflection?
I have created a static helper class ListHelper, with a generic method that takes either Bear or Pinguin as the generic type, and animals as the argument which should return the list of bears if Bear is the generic type.
That doesn't happen. Instead it crashes with this message
: System.Reflection.TargetException: 'Object does not match target type, and I cannot understand why, because the type is correct when I inspect it via the debugger.
Fully "working" example below.
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System;
class ReflectionTrouble
{
static void Main(string[] args)
{
var animals = new Animals
{
Bears = new List<Bear> {new Bear {Name = "Bear1"}, new Bear {Name = "Bear 2"}},
Pinguins = new List<Pinguin> {new Pinguin {Name = "Pingo1"}, new Pinguin {Name = "Pingo2"}}
};
var lists = ListHelper.GetList<Bear>(animals);
foreach (var bear in lists)
{
Console.WriteLine(bear.Name);
}
//expected to have printed the names of the bears here...
}
}
public static class ListHelper
{
public static IEnumerable<T> GetList<T>(Animals animals)
{
var lists = animals.GetType().GetRuntimeProperties().Where(p => p.PropertyType.IsGenericType);
foreach (var propertyInfo in lists)
{
var t = propertyInfo.PropertyType;
var typeParameters = t.GetGenericArguments();
foreach (var typeParameter in typeParameters)
{
if (typeParameter == typeof(T))
{
// This is where it crashes.
var list = (IEnumerable<T>) propertyInfo.GetValue(t);
return list;
}
}
}
return Enumerable.Empty<T>();
}
}
public class Animals
{
public IList<Bear> Bears { get; set; }
public IList<Pinguin> Pinguins { get; set; }
}
public class Bear
{
public string Name { get; set; }
}
public class Pinguin
{
public string Name { get; set; }
}
You are misunderstanding how to call propertyInfo.GetValue. The parameter you are passing to it should be the object whose property value you want to get. So in this case you are wanting the value of the property on animals so that line should be:
var list = (IEnumerable<T>) propertyInfo.GetValue(animals);
With this change your code is returning bears to me.
I think a dictionary would be better solution here instead of reflection. Out of the box a dictionary should be able to handle all of your scenarios and offer much better performance. If you want to encapsulate it in a class then it might look like this.
public interface IAnimal
{
string Name { get; set; }
}
public class Animals
{
private readonly ConcurrentDictionary<Type, IList<IAnimal>> AnimalDictionary;
public Animals(IList<IAnimal> animals)
{
this.AnimalDictionary = new ConcurrentDictionary<Type, IList<IAnimal>>();
this.Add(animals);
}
public Animals(IAnimal animal)
{
this.AnimalDictionary = new ConcurrentDictionary<Type, IList<IAnimal>>();
this.Add(animal);
}
public IList<IAnimal> Get<T>() where T : IAnimal
{
if (this.AnimalDictionary.ContainsKey(typeof(T)))
{
return this.AnimalDictionary[typeof(T)];
}
return (IList <IAnimal>)new List<T>();
}
public void Add(IList<IAnimal> animals)
{
foreach (IAnimal animal in animals)
{
this.Add(animal);
}
}
public void Add(IAnimal animal)
{
this.AnimalDictionary.AddOrUpdate(animal.GetType(),
new List<IAnimal>{animal},
(type, list) =>
{
list.Add(animal);
return list;
});
}
}

Call one method with parent class instead of two with childs

I have classes:
public class Throw
{
public double speed { get; set; }
public double accurency { get; set; }
}
public class FastThrow : Throw{}
public class LowThrow : Throw{}
Instead of having:
public static FastThrow SetFastThrow(List<object> args)
{
return new FastThrow
{
speed = (double)args[0],
accurency = (double)args[1]
};
}
public static LowThrow SetLowThrow(List<object> args)
{
return new LowThrow
{
speed = (double)args[0],
accurency = (double)args[1]
};
}
I want to have one with parent class:
public static Throw SetThrow(List<object> args)
{
return new Throw
{
speed = (double)args[0],
accurency = (double)args[1]
};
}
To declare list or some other generic interface with child class with instance of parent class. Then adding new elements to existing collection. I know that below example has compilation errors, but it should look like:
List<List<object>> firstList = new List<List<object>>();
public void Main()
{
IList<FastThrow> secondList = new List<Throw>();
foreach (var item in firstList)
{
secondList.Add(SetThrow(item));
}
}
I read about contravariance and do not know if this is possible.
You can't. Rahter than
To declare list or some other generic interface with child class with
instance of parent class.
you should
To declare list or some other generic interface with parent class with
instance of chidlren class.
The second way, as Anirban said, use generic classes, refactor your SetThrow method as following:
public static T SetThrow<T>(List<object> args) where T : Throw, new()
{
return new T
{
speed = (double)args[0],
accurency = (double)args[1]
};
}
So that you can use SetThrow method only to generate different kinds of classes as long as they are child classes. e.g:
IList<FastThrow> secondList = new List<FastThrow>();
foreach (var item in firstList)
{
secondList.Add(SetThrow<FastThrow>(item));
}
And generic classes are strong typed and elegant to use.

Enumerator behavior changes based on how we reference it?

Wrapping a reference to the list's enumerator inside a class seems to change its behavior. Example with an anonymous class:
public static void Main()
{
var list = new List<int>() { 1, 2, 3 };
var an = new { E = list.GetEnumerator() };
while (an.E.MoveNext())
{
Debug.Write(an.E.Current);
}
}
I would expect this to print "123", but it only prints zero and never terminates. The same example with a concrete class:
public static void Main()
{
var list = new List<int>() { 1, 2, 3 };
var an = new Foo()
{
E = list.GetEnumerator()
};
while (an.E.MoveNext())
{
Debug.Write(an.E.Current);
}
}
public class Foo
{
public List<int>.Enumerator E { get; set; }
}
What's going on?
I tested it and for me it does not work with your concrete class either.
The reason is that List<T>.Enumerator is a mutable struct and an.E is a property.
The compiler generates a backing field for each auto-property like this:
public class Foo
{
private List<int>.Enumerator _E;
public List<int>.Enumerator get_E() { return E; }
public void set_E(List<int>.Enumerator value) { E = value; }
}
A struct is a value-type, so every-time you access an.E you get a copy of that value.
When you call MoveNext() or Current, you call it on that copy and this copy is mutated.
The next time you access an.E to call MoveNext() or Current you get a fresh copy of the not-yet-iterated enumerator.
And an.E.Current is 0 instead of 1 because - again - you get a fresh enumerator that MoveNext() was not yet called upon.
If you want to store a reference of the list's enumerator you could declare your class Foo with a property of type IEnumerator<int>:
public class Foo
{
public IEnumerator<int> E { get; set; }
}
If you assign E = list.GetEnumerator(); now, the enumerator gets boxed and a reference instead of a value is stored.

How to reference an existing class variable using a string?

I want to get a reference to an existing class variable using a string. I have seen some examples of similar things but can seem to figure this one out.
Please help with the commented section!
public class MyClass
{
public int myInt;
public MyClass( int i)
{
myInt = i;
}
}
void Start ()
{
MyClass myclass = new MyClass(1);
MyClass myOtherClass = //Should be equal to myClass BUT I want to use the string "myClass" to reference it.
}
Local variables cannot be accessed by string name, even using reflection. One option is to store them in a dictionary:
var dict = new Dictionary<string, MyClass>();
dict.Add("myClass", myClass);
string varName = "myClass";
MyClass myOtherClass = dict[varName];
But it's not clear at all why you want to access it by string name. I suspect there's a better solution for your real problem.
Though the question is kind of weird, but here is the stupid solution:
var instances = new Dictionary<string, MyClass>();
MyClass instance= new MyClass(1);
//the string "instance" can be replaced with "nameof(instance)" using C# 6.0
instances.Add("instance", instance);
To access this instance by name:
MyClass myOtherInstance = instances["instance"];
Wierd question, curious to know if this is what you wanted:
public class MyClass
{
public int myInt;
public MyClass(int i)
{
myInt = i;
}
}
public class Starter
{
private MyClass myclass;
public void Start()
{
myclass = new MyClass(1);
var type = this.GetType();
var variable = type.GetField("myclass", BindingFlags.NonPublic | BindingFlags.Instance);
MyClass myOtherClass = (MyClass)variable.GetValue(this);
}
}

C# Returning custom class Array

I have a custom class defined:
class Car
{
public string a;
public string b;
public string c;
public static void GetCar()
{
var car = new Car[4];
for(int i=0; i<4; ++i)
{
novica[i]= new Novica();
novica[i].a="abc";
novica[i].b="abc";
novica[i].c="abc";
}
}
}
This fills the array with values, and now I would like to use this array with the values it gets (loading string from HTML) in a function that is not part of this class. Is it possible and if so, how?
In order to use it elsewhere, you would need to return the array from your function, like so:
public static Car[] GetCar()
{
var car = new Car[4];
for(int i=0; i<4; ++i)
{
car[i]= new Novica();
car[i].a="abc";
car[i].b="abc";
car[i].c="abc";
}
return car;
}
You can't. Your method doesn't actually return anything.
If you were to change the method signature to return the array the method creates:
public static Car[] GetCar()
{
// Body
return car;
}
The call would become as simple as:
var cars = Car.GetCar();
I suggest a slightly different construction. Provide an array containing all cars as static property
public class Car
{
public static Car[] AllCars { get; private set; }
public Car()
{
// Class and constructor somewhat simplyfied.
AllCars = new Car[4];
for (int i = 0; i < 4; ++i) {
AllCars[i] = new Novica();
}
}
}
Now you can work with cars like this
foreach (Car car in Car.AllCars) {
// do something with car
}
Or access a specific car with
string a = Car.AllCars[i].a;

Categories