Dynamically create objects based on a runtime count value - C# - c#

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);
}

Related

How can I add objects Cbook to my class CBooks without using lists

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?

How can i dynamically create an objects of the class?

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());
}

Using GetEnumerator for Dictionary initialization C#

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>()));

Class Wide Array in C#

I'm trying to create a class wide array in C#, in a Windows Mobile Phone 8.1 project, so that when I create a method I can
What I did at first was:
public sealed partial class GamePage : Page
{
int Score = 0;
int count = 0;
private DispatcherTimer Timer;
public ColorsClass color = new ColorsClass();
public int RandBlue = 0;
int RandGreen = 0;
int RandRed = 0;
int RandYellow = 0;
int RandPurple = 0;
int RandYellowGreen = 0;
int RandOrange = 0;
int RandGray = 0;
bool Equal = true;
int Fail;
int Hit;
int Lives = 10;
Rectangle[] Block = { Block01, Block02, Block03, Block04, Block05, Block06, Block07, Block08, Block09, Block10, Block11, Block12 };
int[] RandomColors = { RandBlue, RandGreen, RandRed, RandYellow, RandPurple, RandYellowGreen, RandGray };
...
}
But it gives me the message that "a field initializer cannot reference the non-static field, method or property..."
Then I tried this option, that I saw when I was search in the internet:
public sealed partial class GamePage : Page
{
int Score = 0;
int count = 0;
private DispatcherTimer Timer;
public ColorsClass color = new ColorsClass();
public int RandBlue = 0;
int RandGreen = 0;
int RandRed = 0;
int RandYellow = 0;
int RandPurple = 0;
int RandYellowGreen = 0;
int RandOrange = 0;
int RandGray = 0;
bool Equal = true;
int Fail;
int Hit;
int Lives = 10;
int []
Random rand = new Random();
public GamePage()
{
this.InitializeComponent();
DispatchTheTime();
RandomColors = new int[] { RandBlue, RandGreen, RandRed, RandYellow, RandPurple, RandYellowGreen, RandGray };
...
}
This way I can reach the array through the methods I created, but the array values are always null..
What can I do?
Everytime when you create a new GamePage you are filling your array with the content of the variables RandGreen, RandRed, ...
At this time, these variables are set to 0. Thus your array contains only 0s. Even if you later assign other values to RandGreen, RandRed, ... the values within the array will not change.
I hope this example will make it clearer:
RandBlue = 0;
var RandomColors = new int[] { RandBlue, RandGreen };
// RandColors[0] is 0
RandBlue = 5;
// RandColors[0] is still 0
Edit:
The error message "a field initializer cannot reference the non-static field, method or property..." should be self-explaining. You could make your color variables const in order to make it work. But I suppose this would not make any sense for you.
Keep in mind that integers are valuetypes. If you create an array of integers like with the RandomColors, you'll just put a copy of your value in the array. At this point, RandGreen and RandomColors[1] point to different memory locations and a change of either won't propagate to the other.
You have to decide whether you want to keep your values in a lot of fields like you actually declared or if you want to keep your integers in an array.
You are propably better off using a Dictionary for your usecase and only access the integers from there.
On class level declare your RandomColors:
Dictionary<string, int> RandomColors = new Dictionary<string, int>();
public GamePage()
{
RandomColors.Add("RandGreen", 0);
RandomColors.Add("RandRed", 0);
//change like this:
RandomColors["RandGreen"] = 5;
//access like this:
int x = RandomColors["RandGreen"];
}

Unit testing with NUnit. Null object error

I keep getting a null object reference error when im running one of my unit test.
Unit Test:
[Test]
public void EnumeratedData_ValidInputType_NoErrorAdded()
{
List<String> errorMessageList = new List<string>();
UserInputEntity myEntity = new UserInputEntity();
myEntity.DataTypes = new List<string>();
myEntity.DataTypes.Add("DateTime");
myEntity.DataTypes.Add("datetime");
myEntity.DataTypes.Add("decimal");
myEntity.DataTypes.Add("decIMAL");
myEntity.DataTypes.Add("DOUble");
myEntity.DataTypes.Add("double");
myEntity.DataTypes.Add("FLOat");
myEntity.DataTypes.Add("float");
myEntity.DataTypes.Add("INT");
myEntity.DataTypes.Add("int");
PathReader reader = new PathReader();
IOManager manager = new IOManager(reader);
VerificationManager testObject = new VerificationManager(manager);
testObject.EnumeratedDataTypes(myEntity, errorMessageList);
Assert.AreEqual(errorMessageList.Count, 0);
}
Method Code:
public void EnumeratedDataTypes(UserInputEntity inputs, List<String> errorMessageList)
{
inputs.EnumeratedDataTypes = new int[inputs.DataTypes.Count];
try
{
for (int i = 0; i < inputs.DataTypes.Count; i++)
{
inputs.EnumeratedDataTypes[i] = (int)Enum.Parse(typeof(Enumerations.ColumnDataTypes), inputs.DataTypes[i].ToUpper());
}
}
catch (Exception ex)
{
errorMessageList.Add(ex.Message);
}
}
Enum:
class Enumerations
{
public enum ColumnDataTypes
{
DATETIME = 0,
DECIMAL = 1,
DOUBLE = 2,
FLOAT = 3,
INT = 4
}
}
ErrorMessage:
FrazerMann.CsvImporter.Entity.Test.EntityVerificationTests.EnumeratedData_ValidInputType_NoErrorAdded:
System.NullReferenceException : Object reference not set to an instance of an object.
Im assumin im overlooking something stupidly simple but i cant see it. id appreciate it if someone could put me out of my misery.
In your EnumeratedDataTypes method, you first set the length of the inputs.EnumeratedDataTypes property to inputs.ColumnNames.Count, which is equal to 0 since it has not been filled with data yet (it is only the List capacity that has been set to 9).
Next, when filling this array property with data you loop from 0 to index (including) inputs.DataTypes.Count:
for (int i = 0; i <= inputs.DataTypes.Count; i++)
I count the size of the input.DataTypes list to 10. Thus, you will try to write data to an empty array.
I propose the following changes:
First, initialize the inputs.EnumeratedDataTypes array as follows:
inputs.EnumeratedDataTypes = new int[inputs.DataTypes.Count];
Second, use < instead of <= in the for loop:
for (int i = 0; i < inputs.DataTypes.Count; i++)

Categories

Resources