I have a class MyClass:
public class OPCTag
{
public string tagName;
public string tagOvationMatch;
public string tagValue;
}
I know how to create an object of class manually, but how can i dynamically create and objects of this class ? For example, to create it at the for cycle:
for (int i=0; i< 10; i++)
{
//CREATE OBJECT DYNAMICALLY
}
To get after it a 10 objects of MyClass.
If you mean simply creating an instance of a class always with the same type, then this will be enough for you:
List<OPCTag> list = new List<OPCTag>();
for (int i = 0; i < 10; i++)
{
// Create object of OPCTag
var obj = new OPCTag();
// Set value for 'tagName' property
obj.tagName = "New value of 'tagName'";
// Get value of 'tagName' property
var tagNameValue = obj.tagName;
list.Add(obj);
}
// Set value of 4th element 'tagName' property
list[4].tagName = "This is 4th element";
// Get value of 4th element 'tagName' property
var valueOf4thTag = list[4].tagName;
But if you want to create classes dynamically with unknown types, you should use reflection:
// Type namespace and name
string typeName = typeof(OPCTag).FullName; // MyNamespace.OPCTag
List<Object> list = new List<Object>();
for (int i = 0; i < 10; i++)
{
// Create object dynamically from string type
var obj = Type.GetType(typeName).GetConstructor(new Type[0]).Invoke(new object[0]);
// Set value for 'tagName' property
obj.GetType().GetProperty("tagName").SetValue(obj, "New value for 'tagName'");
// Get value from 'tagName' property
string tagNameValue = (string)obj.GetType().GetProperty("tagName").GetValue(obj);
list.Add(obj);
}
You can add your objects dynamically in a loop, but you have to create a list.
You can write something like that :
List<OPCTag> lstTag = new List<OPCTag>();
for(int i = 0; i<10 ; i++)
{
lstTag.Add(new OPCTag());
}
//Your class
public class OPCTag
{
public string tagName;
public string tagOvationMatch;
public string tagValue;
}
// Initialize new list object of type OPCTag
List<OPCTag> lstTag = new List<OPCTag>();
for(int i = 0; i<10 ; i++)
{
lstTag.Add(new OPCTag());
}
//To read value from lstTag based on index here I specify the 0 index / first value in list.
var firstIndexTagname = lstTag[0].tagName;
var firstIndexTagOvationMatch = lstTag[0].tagOvationMatch;
var firstIndexTagValue = lstTag[0].tagValue;
To create 10 objects of MyClass you can do, for example:
List<MyClass> list = new List<MyClass>();
for (int i = 0; i < 10; i++)
{
list.Add(new MyClass());
}
Though it's not "dynamically creating objects", just creating instances.
For Dictionary you should specify key and value. They can be of any type, not just int (usually string).
Dictionary<int, MyClass> dictionary = new Dictionary<int, MyClass>();
for (int i = 0; i < 10; i++)
{
dictionary.Add(i, new MyClass());
}
Related
Please check the code below. I am trying to set value to a random property of a int list. Problem is that even after i set 5 to a random list this value getting inserted to that property. What am I doing wrong here?
var TransactionList = new List<int>();
for (int i = 0; i < 59; i++)
{
TransactionList.Add(0);
}
var randTransaction = TransactionList.OrderBy(x => Guid.NewGuid()).FirstOrDefault();
//here i am trying to set 5 value to a random TrnasactionList but this not being set
randTransaction = 5;
Try like below. new Random().Next(0, 59); will return value between 0 and 59. Or you can better set it like new Random().Next(0, TransactionList.Count); for it to be dynamic with list.
new Random().Next(minValue, maxValue); The maxValue for the upper-bound in the Next() method is exclusive—the range includes minValue, maxValue-1, and all numbers in between.
var TransactionList = new List<int>();
for (int i = 0; i < 59; i++)
{
TransactionList.Add(0);
}
// var index = new Random().Next(0, 59);
// Below will work for dynamic length of list.
var index = new Random().Next(0, TransactionList.Count);
TransactionList[index] = 5;
If you don't mind the original list getting sorted you could do this:
class Program
{
static void Main(string[] args)
{
var transactionList = new List<int>();
for (int i = 0; i < 59; i++)
{
//I initialized the list with i instead of 0 to better see sorting in place
transactionList.Add(i);
}
transactionList.Sort(new RandomComparer());
//changed it to 99 to spot it more easily
transactionList[0] = 99;
foreach (var i in transactionList)
Console.WriteLine(i);
}
}
public class RandomComparer : IComparer<int>
{
private Random _random = new Random();
public int Compare(int x, int y)
{
return _random.Next(-1, 2);
}
}
See it in action:
https://dotnetfiddle.net/NKuPdx
randTransaction is "int" data type, which is primitive data type.
if you want to set randTransaction that reflect to it's object, just set the object it self
Cbooks has an atribute "CTeam[] Teams" and it is of fixed size (8). If I want to add objects to it using this in the Main:
CBook A1 = new CBook("Title1", "Author1");
CBook A2 = new CBook("Title1", "Author2");
CBooks ArrayOfBooks = new CBooks(8);
ArrayOfBooks.Add(A1);
ArrayOfBooks.Add(A2);
then position 0 and 1 are ocuppied, and the positions from 2 to 7 are null. What I want to do is, using a variable "int aux=0", count the ocupied positions like this:
for (int k = 0; k < NumberOfTeams; k++)
{
if (Teams[k].Name=="")
Aux += 1;
}
So, Aux in this case would be 2, then I want to do "Teams[Aux] = A" so that A would be in the position 2 and now I should have three objects in my array. But I'm getting "Index out of bound"
Your implementation then should look similar to this:
public class Program
{
public static void Main(string[] args)
{
Element a = new Element("A");
Element b = new Element("B");
MyArray array = new MyArray(8);
array.Add(a);
array.Add(b);
Console.WriteLine(array.Count()); //2 Elements are in the array
}
}
//Sample element class.
public class Element{
public readonly String MyString;
public Element(String myString){
MyString = myString;
}
}
//Sample array class.
public class MyArray{
private readonly Element[] myArray;
private int count; //Use a property here
public MyArray(int size){
//Be careful -> check if size is >= 0.
myArray = new Element[size];
}
public bool Add(Element element){
if(myArray.Length == count) // return false if no more elements fit.
return false;
myArray[count] = element;
count++;
return true;
}
public int Count(){
return count;
}
}
So there is no need for creating an extra count loop. Your "count" variable in "MyArray" class holds always the correct value.
Anyway the implementation or use case of this code is a little bit clunky.
Why are you cant use directly a more safe list or something. That would be a better solution.
What do you need CBooks for? From what I understand, it's just an array of 8 CBook objects so why not use CBook[]?
CBook A1 = new CBook("Title1", "Author1");
CBook A2 = new CBook("Title1", "Author2");
CBooks[] ArrayOfBooks = new CBook[8];
ArrayOfBooks[0] = A1;
ArrayOfBooks[1] = A2;
int aux = 0;
for (int k = 0; k < ArrayOfBooks.Length; k++)
{
//break the loop because we know there are no more books
if (ArrayOfBooks[k] == null)
break;
aux++;
}
The question doesn't cover what the variables NumberOfTeams and Teams are for but could those be added to the implementation of CBook?
I have a class Cluster.cs defined as:
public class Cluster
{
protected int _clusterID = -1;
private static int _clusterCount = 0;
protected int _attributeCount;
// _clusterObjects contains EvoObjects in this cluster.
protected List<EvoObject> _clusterObjects = new List<EvoObject>();
/** _nkA[_i] is the total occurrences of the attribute _i in this cluster*/
protected Int32[] _nkA;
// For each attribute, record their values as KeyValuePair.
protected Dictionary<Int32, UtilCS.KeyCountMap<Int32>> _attributeValues = new Dictionary<Int32, UtilCS.KeyCountMap<Int32>>();
public Cluster(int _clusterID, int _attributeCount)
{
this._clusterID = _clusterID;
this._attributeCount = _attributeCount;
_nkA = new Int32[_attributeCount];
}
// Initialize _attributeValues
IEnumerable<Int32> _range = Enumerable.Range(0, _attributeCount).GetEnumerator(_i => {_attributeValues[_i] = new UtilCS.KeyCountMap<Int32>()});
}
while initializing _attributeValues, I got error as:
"No overloaded method for GetEnumerator takes 1 argument"
whereas I've only 1 argument to initialize i.e. _attributeValues which is actually a dictionary that's why have to enumerate at it.
Also if I declare _attributeCount static, I'm unable to use it in constructor and if I declar it non-static, I'm unable to use it Range method of Enumberable.
How will I initialize _attributeValues then?
How to declare _attributeCount static or non-static?
It looks like your trying to initialize the Dictionary by using a variable (_range) that is set at object creation. This should be moved into the constructor. It appears you are attempting to create three new attributes with keys 0,1,2 and values of new UtilCS.KeyCountMap().
If this is correct, then I would suggest using this as your constructor.
public Cluster(int _clusterID, int _attributeCount)
{
this._clusterID = _clusterID;
this._attributeCount = _attributeCount;
_nkA = new Int32[_attributeCount];
for (var i = 0; i < 3; i++)
{
_attributeValues.Add(i, new UtilCS.KeyCountMap<int>());
}
}
However, since you are sending in _attributeCount I would say you could use that instead of 3.
public Cluster(int _clusterID, int _attributeCount)
{
this._clusterID = _clusterID;
this._attributeCount = _attributeCount;
_nkA = new Int32[_attributeCount];
for (var i = 0; i < _attributeCount; i++)
{
_attributeValues.Add(i, new UtilCS.KeyCountMap<int>());
}
}
Enumerable.Range(0, _attributeCount).ToList().ForEach(x => _attributeValues.Add(x, new UtilCS.KeyCountMap<Int32>()));
I have a loop:
List<A> list = new List<A>();
A obj = new A();
for (int i = 0; i < 10; ++i)
{
obj.num = i; // Assigns the current i to the num attribute inside obj
list.Add(obj);
}
However, in this case, whenever I modify obj, the previous instances of obj already added into the list will be modified. How do I write the code such that whatever that is added into the list has no more reference to the current value of obj?
You can create a new List<A> via Linq instead of adding:
List<A> list = Enumerable
.Range(0, 10)
.Select(i => new A() { num = i })
.ToList();
If you prefer adding
List<A> list = new List<A>();
for (int i = 0; i < 10; ++i)
list.Add(new A() {num = i}); // <- Adding new (copied) instance
you should move declaration of obj variable inside for loop
List<A> list = new List<A>();
for (int i = 0; i < 10; ++i)
{
A obj = new A();
obj.num = i; // Assigns the current i to the num attribute inside obj
list.Add(obj);
}
it is all just about variable scopes. here obj scope is inside a for loop iteration. if you want to use a variable between iterations you should define it out of for loop like the way you have declared obj before.
That's happening because probably A obj = new A(); is a ByReference object. So whenever you're in the loop, it's also changing the object you added on the List.
What you can do is either
Create the object inside the loop and then add it.
for (int i = 0; i < 10; ++i)
{
A obj = new A(); // create here so it's a new object always
obj.num = i; // Assigns the current i to the num attribute inside obj
list.Add(obj);
}
Make the A type IClonable
class A : ICloneable
{
public object Clone()
{
return this.MemberwiseClone();
}
}
and then just cast in before adding.
List<A> list = new List<A>();
A obj = new A();
obj.num = 0;
for (int i = obj.num; i < 10; ++i)
{
var clonedObj = obj.Clone() as A; // cast to be able to add in the collection
clonedObj.num = i;
list.Add(clonedObj);
}
Simple example of scenario I am trying to implement
class ATest
{
int a;
int b;
BTest[];
}
class BTest
{
int X;
int Y;
}
I need to create ATest and BTest dynamically based on a value.
I tried it as Atest[] aobj = new Atest[count]; (This count value will be set programmatically)
Now I need to create Array of Objects of B dynamically and assign it to A
Currently I assume static value for count and assigned it
Atest[] aobj = new Atest[20];
BTest[] bobj = new BTest[1];
bobj[0] = new Btest();
aobj[0] = new ATest();
aobj[0].BTest = bobj;
BTest[] bobj1 = new BTest[1];
bobj1[0] = new Btest();
aobj1[0].BTest = bobj1;
This may not be the best way to code.
Please suggest on dynamically implementing it
- Dynamically create number of BTest object arrays and assign it for ATest instances
Try using constructors:
class ATest {
int a;
int b;
BTest[] btests;
public ATest(int numOfB) {
btests = new BTest[numOfB];
}
}
The you can create and initialize your atests in a simple loop:
int M = 20; // Number of Test A objects
int N = 10; // Number of Test B objects per Test A
var atests = new ATest[M];
for (var i = 0 ; i != M ; i++) {
atests[i] = new ATest(N);
}