Access own class properties during creation - c#

When initially creating a new class record, how can you access its own properties?
Below is my example structure which I am wanting to set Total as the sum of No1 and No2
class ROWDATA
{
public int No1;
public int No2;
public int Total;
}
ROWDATA RowData = new ROWDATA
{
No1 = reader.GetInt32(reader.GetOrdinal("fuel_tank_no_1")),
No2 = reader.GetInt32(reader.GetOrdinal("fuel_tank_no_2")),
Total = No1 + No2 // this does not work
};
I get an error stating that The name 'No1' does not exist in the current context

You can update the Total property like this:
public int Total { get { return No1 + No2; } }
You can use this also:
var RowDataNo1 = reader.GetInt32(reader.GetOrdinal("fuel_tank_no_1"));
var RowDataNo2 = reader.GetInt32(reader.GetOrdinal("fuel_tank_no_2"));
ROWDATA RowData = new ROWDATA
{
No1 = RowDataNo1,
No2 = RowDataNo2,
Total = RowDataNo1 + RowDataNo2
};

You are using object initialiser syntax and in there you do not have access to read properties. You can either use the two values you've already read or change the property.
Using the values
ROWDATA RowData = new ROWDATA
{
No1 = reader.GetInt32(reader.GetOrdinal("fuel_tank_no_1")),
No2 = reader.GetInt32(reader.GetOrdinal("fuel_tank_no_2")),
Total = reader.GetInt32(reader.GetOrdinal("fuel_tank_no_1")) +
reader.GetInt32(reader.GetOrdinal("fuel_tank_no_2"))
};
In this case it would probably be preferable to store the values in variables and use them rather than repeated access to the reader object.
Change Total Property
The preferred option is to change your Total property to something like this:
public int Total
{
get { return No1 + No2; }
}

As stated by DavidG, you do not have access to get property accessors when using object initialiser syntax.
The C# specification1 specifically states
It is not possible for an object or collection initializer to refer to the object instance being initialized.
1 Specifically, C# 3.0 spec, section 26.4 Object and Collection Initializers

Related

Alternate to 2D array in C#

I have to store two types of information in any data structure for what I came up with the scrap solution of 2D array in C#. I have to store as:
number of cluster in int data type
cluster membership count in int data type
If I use a 2D array as:
Int32[,] _clusterMembership = new Int32[10, 10];
But the issue here is:
I don't know what total number of cluster will be?
I don't know what number of members each cluster will have?
So the question is:
How can I manage to store this information in C# ?
ADDENDUM
I have to use answer from this question here in this method as:
public static List<Cluster> DP_Cluster(List<string> _customer, double _alpha)
{
var _currentClusters = 0; // current number of clusters i.e. "k"
var _memberNumber = 0; // running member number i.e. "n"
//var _dic = new Dictionary<int, List<string>>();
var _probOld = 0.0;
var _probNew = 0.0;
List<Cluster> myClusters = new List<Cluster>();
Cluster cluster = new Cluster(_currentClusters += 1);
cluster.Members.Add(new ClusterMember { Name = _customer.ElementAt(_memberNumber) });
myClusters.Add(cluster);
//_dic.Add(_currentClusters, _customer.ElementAt(_memberNumber));
_currentClusters += 1;
for(int _i = 1; _i < _customer.Count - 1; _i++)
{
if( _i <= _currentClusters)
{
_probOld = myClusters[_i].Members.Count / ((_i+1) - 1 + _alpha);
}
else
{
_probNew = _alpha / ((_i+1) - 1 + _alpha);
}
if(_probNew > _probOld)
{
// Add _customer.ElementAt(_memberNumber+=1) to New Cluster
Cluster cluster = new Cluster( _currentClusters += 1 ); // Here is an error as we defining same name for another cluster
myClusters.Add(cluster);
}
else
{
// Add _customer.ElementAt(_memberNumber+=1) to Old Cluster
}
}
return myClusters;
}
How should I update my method to get desired results?
You should consider making two types, one for the clusters and one for the members:
Members
public class ClusterMember
{
public string Name {get;set;}
// more properties...
}
Clusters
public class Cluster
{
public int ID {get;}
public List<ClusterMember> Members {get;}
public Cluster(int id)
{
ID = id;
Members = new List<ClusterMember();
}
}
And then you can store your clusters in a list
List<Cluster> myClusters = new List<Cluster>();
Cluster cluster = new Cluster(1);
cluster.Members.Add(new ClusterMember { Name = "Member1" });
myClusters.Add(cluster);
UPDATE I assumed that you want to do more with your data than just store these two information and tried to provide a better object-oriented approach.
To get your counts:
int totalNumberOfClusters = myClusters.Count;
int numberOfMembersInOneCluster = cluster.Members.Count;
int totalNumberOfClusterMembers = myClusters.Sum(c => c.Members.Count);
And to output the number of members for each cluster:
foreach(Cluster c in myClusters)
Console.WriteLine($"Cluster {c.ID} has {c.Members.Count} members.");
As is already mentioned. You can simply use a list. The bottom code example shows how to create the list type you need and how you add and access values in that list.
using System.IO;
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
//Creating a list of lists that contains integers
List<List<int>> clusters = new List<List<int>>();
//each list in the above list consists of a list of integers. So we need to add list of integers to that list
List<int> row = new List<int>();
//now we add integers to the list
row.Add(1); row.Add(2); row.Add(3); row.Add(4);
//Now we add the list of integers to the list of lists of integers
clusters.Add(row);
foreach(List<int> rows in clusters)
{
foreach(int num in rows)
{
System.Console.WriteLine(num);
}
}
Console.WriteLine("number of rows: {0}", clusters.Count);
Console.WriteLine("number of elements in the first row: {0}", clusters[0].Count);
}
}
You could consider using a list of lists;
List<List<int>> clusters;
See this answer on another question for more info and also how to make it into a more generic class: https://stackoverflow.com/a/1596563/6065552
You can store your data in a list which has keyvaluepair items.
Or use Dictionary
List<KeyValuePair<int, int>>()
Dictionary<int,int>();
so you can add new keyvaluepair for each cluster.
static void Main(string[] args)
{
var clusterMembership = new Dictionary<int, int>();
//Add cluster 123 and assign a member count of 4
clusterMembership.Add(123, 4);
//Change member count for cluster 123 to 5
clusterMembership[123] = 5;
//Remove cluster 123
clusterMembership.Remove(123);
//Get the number of clusters in the dictionary
var count = clusterMembership.Count;
//Iterate through the dictionary
foreach(var clusterKey in clusterMembership.Keys)
{
var memberCount = clusterMembership[clusterKey];
}
}

how set value in dictionary when content a dictionary and class

I defined the variable below:
Dictionary<clssMenu_Item, Dictionary<clssMenu_Item, List<clssMenu_Item>>> dicMenu =
new Dictionary<clssMenu_Item, Dictionary<clssMenu_Item, List<clssMenu_Item>>>();
The type clssMenu_Item is defined as:
class clssMenu_Item
{
public string name;
public string text;
}
I have a string (I call strKey) already assigned to the text property of clssMenu_Item inside dicMenu. It's clear text is part of key. I want to search dicMenu to find value of strKey in all over of dictionary such as its sub. I don't know how can get this value?!
this method calculates the key of the dictionary:
private List<clssMenu_Item> GetFormButtons(Form form)
{
List<clssMenu_Item> ListBtn = new List<clssMenu_Item>();
foreach (Control c in GetAllControls<Button>(form))
{
int btnIndex= c.Name.IndexOf("btn");
if (btnIndex != 0) // find all of the determined buttons
{
clssMenu_Item objBtn = new clssMenu_Item();
objBtn.name = c.Name.ToString();
objBtn.text = c.Text;
ListBtn.Add(objBtn);
}
}
return ListBtn;
}
here is how I populate the key:
foreach (var k in objH.mainForm) //fill dicMenu
{
dicMenu.Add(k,null);
}
The reason that I'm using a nested dictionary is that this tree has only 3 levels. Each clssMenu_Items has a group of children like itself type. dictionary was my solution to save them.
problem:
now I wanna fill value of keys by below code:
Dictionary<clssMenu_Item, List<clssMenu_Item>> d2 = new Dictionary<clssMenu_Item, List<clssMenu_Item>>();
clssMenu_Item k = new clssMenu_Item();
k.text = strKey;
foreach(var prp in dicMenu.Keys) //we should fill all of the variables in class
{
if (prp.text == strKey)
{ k.name = prp.name; break; }
}
d2= dicMenu[k]; //assign value of key
I dont know why I have error on d2= dicMenu[k]; said k is not in DicMenu, although I debug this block. we have k in DicMenu :( I dont know what should I do?!
is there other way to create a tree?

Sending a list of doubles as strings to the database

Just quite confused with the piece of code below.
I have class like below
public class Counter
{
public Double NormalCounter { get; set; }
public Double SATCounter { get; set; }
public Double SUNCounter { get; set; }
}
in my main class i have method to do some calculation to fill the counter
Counter CountHrs = GetBookedHours(resourceBkg, PrevEvent);
var lstExpResult = new List<string> {CountHrs.NormalCounter.ToString(),
CountHrs.SATCounter.ToString(),
CountHrs.SUNCounter.ToString()};
UpdateBooking(bookingSesid, lstExpResult);
Just assume i have the value like below in the counter
NormalCounter =4
SATCounter=10
SUNCounter=6
am trying to add in to string list and update the database.is that the right way to do ? or any other options i have please.
my update booking method is below to give clear idea.
public static bool UpdateBooking(string BookingSesid,List<string>HoursByRate)
{
SchedwinEntities db = new SchedwinEntities();
string value = string.Empty;
for (int i = 0; i < 5; i++)
{
string str = " ";
if (i < HoursByRate.Count())
{
str = HoursByRate[i];
value += str + ((char)13).ToString() + ((char)10).ToString();
}
}
var query =
from SEVTs in db.SEVTs
where
SEVTs.SESID.Trim() == BookingSesid//SESID
select SEVTs;
foreach (var SEVTs in query)
{
SEVTs.USER3 = value;//value
}
try
{
db.SaveChanges();
return true;
}
catch (UpdateException ex)
{
return false;
}
}
Rather than passing a list of strings that represent doubles, you should pass a list of key-value pairs, construct a parametersized statement from them, and use the list of key-value-pairs to bind parameter values, like this:
class SqlParamBinding {
string Name {get;set;}
object Value {get;set;}
}
var lstExpResult = new List<SqlParamBinding> {
new SqlParamBinding { Name = "NormalCounter", Value = CountHrs.NormalCounter}
, new SqlParamBinding { Name = "SATCounter", Value = CountHrs.SATCounter}
, new SqlParamBinding { Name = "SUNCounter", Value = CountHrs.SUNCounter}
};
UpdateBooking(bookingSesid, lstExpResult);
Now that lstExpResult separates names from values, your UpdateBooking code could format the SQL expression as
WHERE NormalCounter=#NormalCounter AND SATCounter=#SATCounter AND ...
and then bind #NormalCounter, #SATCounter, and #SUNCounter to the values passed in the lstExpResult list.
If it is going to list of Counter classes then have List instead of List. Looks like you might be having bunch of Counter objects that might be getting updated or sent to the database.
Counter c = new Counter();
c. NormalCounter = 4
c.SATCounter = 10
c.SunCounter = 10
List<Counter> listCounter = new List<Counter>
listCounter.Add(c);
Code is more maintainable and readable.
If you are sending one object at a time, then no need of list at all. You can pass in the counter object to your UpdateMethod and parse it while updating the database.

increasing names in C# with integers

I need to get an object and check if it already exists.
In case it does, I want to add a number, or increase the number in its name.
For example if I have the object "a" and it exists, I need to add a 1 so it's called a1.
In case a1 exists, a2, etc.
How could I perform this?
My code:
if (e.TreeNode.Tag is Variant)
{
if (variantExists(e.TreeNode.Text))
{
Random r = new Random();
int randomNumber = r.Next(0, 99);
e.TreeNode.Text = e.TreeNode.Text + randomNumber;
//e.TreeNode.Remove();
return;
}
}
Can you change the TreeNode class? I would add properties for Label (Name without Index) and Index and make the Name property read only, i.e
class TreeNode
{
public int Index {get;set;}
public string Label {get;set;}
public string Name
{
get { return Index == 0 ? Label : Label + Index; }
}
}
In your code you just need to set the Index property to the value you need and dont worry about the whole string parsing stuff
string name = "SomeName";
string tempName = name;
int n = 0;
while (DoesNameExist(tempName))
{
n++;
tempName = name + n;
}
name = tempName;
This gets ineffecient for large numbers of the same object, but that shouldn't happen right?
The problem with doing it the other way around, and stripping off trailing numbers to find the "original" name is that the original name may genuinely have numbers on it.
Eg. You say you add:
SomeName
SomeName99
SomeName
SomeName99
The above code will give you
SomeName
SomeName1
SomeName99
SomeName991
Something along the lines of this could work:
var existingItems = new HashSet<string>();
var items = new List<string>{"a", "b", "a"};
foreach (var item in items)
{
var tempItem = item;
var i = 1;
while (!existingItems.Add(tempItem))
tempItem = tempItem + i++;
}

How duplicate an object in a list and update property of duplicated objects?

What would be the best way to duplicate an object placed in a list of items and change a property of duplicated objects ?
I thought proceed in the following manner:
- get object in the list by "ref" + "article"
- Cloned the found object as many times as desired (n times)
- Remove the object found
- Add the clones in the list
What do you think?
A concrete example:
Private List<Product> listProduct;
listProduct= new List<Product>();
Product objProduit_1 = new Produit;
objProduct_1.ref = "001";
objProduct_1.article = "G900";
objProduct_1.quantity = 30;
listProducts.Add(objProduct_1);
ProductobjProduit_2 = new Product;
objProduct_2.ref = "002";
objProduct_2.article = "G900";
objProduct_2.quantity = 35;
listProduits.Add(objProduct_2);
desired method:
public void updateProductsList(List<Product> paramListProducts,Produit objProductToUpdate, int32 nbrDuplication, int32 newQuantity){
...
}
Calling method example:
updateProductsList(listProducts,objProduct_1,2,15);
Waiting result:
Replace follow object :
ref = "001";
article = "G900";
quantite = 30;
By:
ref = "001";
article = "G900";
quantite = 15;
ref = "001";
article = "G900";
quantite = 15;
The Algorithm is correct? Would you have an idea of the method implementation "updateProductsList"
Thank you in advance for your help.
First, it looks like you want to implement your own ProductList object. The implementation is simple, when extending List<Product>. Second, to update the product, you can remove the old product, clone it twice and add it twice.
public class ProductList : List<Product> {
public void update(Product product, int nrOfDuplications, int newQuantity) {
Remove(product);
for(int i = 0; i < nrOfDuplications; i++) {
Add(new Product() {
ref = product.ref,
article = product.article,
quantity = newQuantity
});
}
}
}
This could be further improved by using a copy constructor, which means that you don't need the complete list of all the parts.

Categories

Resources