How to add data items to a List<Struct> - c#

I have the following struct defined in a user control:
public struct ColumnData
{
public string ColumnName { get; set; }
public string ColumnDataItem { get; set; }
public bool ColumnIsHyperLink { get; set; }
public string ColumnHyperLinkURL { get; set; }
public string ColumnHyperLinkPK { get; set; }
}
I create a new instance of List<ColumnData> (In a different code behind that creates an instance of the user control) and want to pass in values to it, but how do I assign them to specific attributes within the struct object?
I create an instance of the struct using the following code:
List<ColumnData> DataItems = new List<ColumnData>();

This:
List<ColumnData> DataItems = new List<ColumnData>();
creates a new list.
This:
List<ColumnData> DataItems = new List<ColumnData>();
var cd = new ColumnData();
cd.ColumnName = "Taco";
DataItems.Add(cd);
creates a new list, a new struct, and adds an item to the list.

Change that to a class; all your woes relating to modifying struct properties (etc) will go away.
Alternatively, make it an immutable struct, and initialize it with the correct values at the point of creation - then the issue is moot, no matter how many times it is subsequently copied.
IMO the first is the right approach here.

so you need to do this:
public void AddToList(ColumnData columnData)
{
DataItems.Add(columnData);
}
and call this method from your other class passing an already created and initialized columnData object.

List<ColumnData> DataItems = new List<ColumnData>();
Is creating the list that holds your structs not your structs itself.
You could use structs here for performance reasons (faster then classes).
ColumnData data = new ColumnData
{
ColumnName = "Blaa"
};
DataItems.Add(data);

Related

How to Insert only values of a class into another list class C#?

image that you defined a class as below;
public class Liste
{
public int valueInt { get; set; }
public List<string> valueString = new List<string>();
}
and I defined a varible which is also a list;
public List <Liste> oray2 = new List <Liste>();
public Liste oray3 = new Liste();
I would like to add value to a oray2 List manually,
oray3.valueInt = 10;
oray3.valueString.Add("Text1");
oray3.valueString.Add("Text2");
oray3.valueString.Add("Text3");
oray2.Add(oray3);
oray3.valueString.Remove("Text2");
This also effects oray2 List. So it seems
oray2.Add(oray3);
is not adding values to oray2 class but oray2[0] seems linked to oray3 class.
So What is the best and efficient way to add values of oray3 to oray2 without a link between oray3 and oray2[0] so resulting changing in oray3 will not affect oray2 list values?
My best solution;
oray3=null;
or
oray3=new Liste();
worked like a charm.
I see two choices: set oray3 to a new Liste object and set its properties rather than reuing the reference, or copy oray3 to a new Liste object and add that to the list.
It's not clear why you're reusing oray3 in the first place to kniw which of those is better.
Just make Liste a struct instead of a class i.e.
public struct Lex
{
public Lex()
{
}
public int valueInt { get; set; } = 0;
public List<string> valueString = new List<string>();
}
Classes in C# a reference type and so are passed by reference whereas structs are value types and so are passed by value.
Reference types pass around a reference to the declared variable so when they are assigned to another variable and changed, both variables are updated.
Value types simply copy their values when assigned so changes only occur on the variable that the changes were made to.
More info on value type and reference types here: https://www.tutorialsteacher.com/csharp/csharp-value-type-and-reference-type
I think this is what you want to do. This way a new oray3 object is created each time you call the GetOray3().
List<Liste> oray2 = new List<Liste>();
oray2.Add(GetOray3());
oray2.Add(GetOray3());
oray2.Add(GetOray3());
static Liste GetOray3()
{
Liste oray3 = new Liste();
oray3.valueInt = 10;
oray3.valueString.Add("Text1");
oray3.valueString.Add("Text2");
oray3.valueString.Add("Text3");
return oray3;
}
public class Liste
{
public int valueInt { get; set; }
public List<string> valueString = new List<string>();
}

Trying to use reflection to concatenate lists of objects

I have below class
public class HydronicEquipment
{
public List<LibraryHydronicEquipment> Source { get; set; }
public List<LibraryHydronicEquipment> Distribution { get; set; }
public List<LibraryHydronicEquipment> Terminals { get; set; }
}
and then i have the below class for "libraryHydronicEquipment"
public class LibraryHydronicEquipment : IEquipmentRedundancy
{
public string Name { get; set; }
public RedundancyStatus RedundancyStatus { get; set; }
public EquipmentRedundancy EquipmentRedundancy { get; set; }
}
I am trying to concatenate the list of "LibraryHydronicEquipment" objects available from all three properties (i.e) from source, distribution and terminal and General concatenate method will looks like as this below
var source = hydronicEquipment.Source;
var distribution = hydronicEquipment.Distribution;
var teriminals = hydronicEquipment.Terminals;
Source.Concat(Distribution).Concat(Terminals)
I am trying to achieve the same using reflection and the code looks like as below
foreach (var (systemName, hydronicEquipment) in hydronicSystemEquipment)
{
bool isFirstSystem = true;
var equipmentList = new List<string> { "Source", "Distribution", "Terminals" };
var redundancyequipmentList = GetRedundancyEquipment(hydronicEquipment, equipmentList);
}
and the method GetRedundancyEquipment is looks like below
private static IEnumerable<IEquipmentRedundancy> GetRedundancyEquipment(HydronicEquipment hydronicEquipment, List<string> equipmentList)
{
IEnumerable<IEquipmentRedundancy> equipmentRedundancies = new List<IEquipmentRedundancy>();
dynamic equipmentResults = null;
foreach(var equipment in equipmentList)
{
var componentList = hydronicEquipment.GetType().GetProperty(equipment).GetValue(hydronicEquipment, null) as IEnumerable<IEquipmentRedundancy>;
equipmentResults = equipmentRedundancies.Concat(componentList);
}
return equipmentResults;
}
The problem here is even though i have Source is having list of objects and Distribution is having list of objects, the equipmentResults is giving only one object instead of list of concatenated objects.
I am trying to return the IEnumerable<IEquipmentRedundancy> at the end using reflection method but it seems not working with the above code.
Could any one please let me know how can i achieve this, Many thanks in advance.
GetRedundancyEquipment should preserve your values instead of reassign the reference with each iteration. Here's the fixed version:
private static IEnumerable<IEquipmentRedundancy> GetRedundancyEquipment(HydronicEquipment hydronicEquipment, List<string> equipmentList)
{
IEnumerable<IEquipmentRedundancy> equipmentRedundancies = new List<IEquipmentRedundancy>();
var equipmentResults = new List<IEquipmentRedundancy>();
foreach (var equipment in equipmentList)
{
var componentList = hydronicEquipment.GetType().GetProperty(equipment).GetValue(hydronicEquipment, null) as IEnumerable<IEquipmentRedundancy>;
equipmentResults.AddRange(equipmentRedundancies.Concat(componentList));
}
return equipmentResults;
}
If we look at what you're doing in GetRedundancyEquipment() it becomes clear.
First you create equipmentRedundancies = new List<IEquipmentRedundancy>();
Then you never modify equipmentRedundancies - e.g. via Add(). It remains an empty list until it goes out of scope and is garbage collected.
In a loop you then repeatedly make this assignment equipmentResults = equipmentRedundancies.Concat(componentList);
That is to say: Assign to equipmentResults the concatenation of componentList to equipmentRedundancies.
Note that Concat() is a lazily evaluated linq method. When you actually enumerate it results are produced. It doesn't modify anything, it's more like a description of how to produce a sequence.
So each time through the loop you're assigning a new IEnumerable that describes a concatentaion of an empty list followed by the property that you retrieved with reflection to equipmentResults. Then at the end you return the final one of these concatenations of an empty list and retrieved property.
If you want all of them together, you should concatenate each of them to the result of the previous concatenation, not to an empty list.

changing data of class list

I try to add new record to my list and change data of it, but it's change all record of array, here is my class and code:
The class:
public class TransportDto
{
public int type { get; set; }
public string url { get; set; }
public int Relationship { get; set; }
}
loading data to my list:
IQueryable<TransportDto> list = _entities.Database.SqlQuery<TransportDto>(filterExpression).AsQueryable();
List<TransportDto> lst = list.ToList();
TransportDto help =lst[1];// adding record like one of my result
lst.Add(help);
Now I try to change value of lst[lst.Count-1] but when I change it , lst[1] change too
lst[lst.Count-1].type=3;
on result both lst[lst.Count-1] and lst[1] changes to 3, but I just try to change one record of array
When you write TransportDto help =lst[1];, you are getting the object at the index of 1. When you add this object to the list, you are adding the same object to the list not a copy of it.
Which means in the list, the indices of 1 and lst.Count-1 point to the same object. When you access the object as lst[lst.Count-1] you are accessing this object and .type=3 makes changes to the object the two indices are pointing to.
If you want a copy of the object in lst[1], consider cloning the object. This could make a copy of the object. You can refer here: How to Clone Objects
To simplify, in your case you can create a clone function like this:
public class TransportDto
{
public int type { get; set; }
public string url { get; set; }
public int Relationship { get; set; }
public TransportDto Clone(){
return new TransportDto{
type = type,
url = url,
Relationship = Relationship
};
}
}
This clone function creates a new object of TransportDto and passes the same values thus creating a copy. Now in your list you can do this:
TransportDto help =lst[1].Clone();
Now help stores a copy of lst[1].

How can i add column name in list generic?

class MyExcelSheets
{
public List MyColumnNames { get; set; }
}
how can i add Excel data's column name in "List MyColumnNames ". it returns to me Object reference not set to an instance of an object.
i want to use above class in:
myexcelSheet = new MyExcelSheets();
myexcelSheet.MyColumnNames = new MyExcelSheets().MyColumnNames;
foreach (DataColumn col in dTable.Columns)
myexcelSheet.MyColumnNames.Add(col.ColumnName.ToString());
How can i solve it? Error: NullReferenceException
Assuming that public List MyColumnNames { get; set; } is actually declared as public List<string> MyColumnNames { get; set; }
The row:
myexcelSheet.MyColumnNames = new MyExcelSheets().MyColumnNames;
Should be:
myexcelSheet.MyColumnNames = new List<string>;
Though it would normally be better to do this in a constructor or something.
The Code myexcelSheet.MyColumnNames = new MyExcelSheets().MyColumnNames; only obtains the reference to the property , but it doesnt instantiate that.
Adding the code
this. MyColumnNames = new List<string>;
in a static constructor will solve the issue , as this part of the code will be called by the run time and we dont have to worry about instantiating state transfer objects (as it is in this case)
E.g.,
static MyExcelSheets(){this. MyColumnNames = new List<string>; }
Thanks,
Vijay

Is there a fast way to transfer all the variables of one identical object into another in C#?

This is probably a simple question. Suppose I have a object called Users and it contains a lot of protected variables.
Inside that Users class I have a method that creates a temporary Users object, does something with it, and if successful, transfers all the variables from the temp Users object into the one I have.
Is there some fast way to transfer all the variables from one Users object into another Users object without doing this using C#?
this.FirstName = temp.FirstName;
this.LastName = temp.LastName;
........75 variables later......
this.FavoriteColor = temp.FavoriteColor
A better approach is to implement the IClonable interface. But you'll find it doesn't save you a lot of work.
You should check out cloning in C#.
Deep cloning objects
I think serializing and then deserializing an object will create a new object instance. This should be identical to the former object.
A better solution might be to move whatever this method is outside of your class, and then just assign the temp user object to your main user object reference like so:
_User = tmpUser;
sparing you the 75 lines of code. Whenever I have a class creating an instance of itself inside one of its own methods, I always like to blink a couple of times and make sure I really need to be doing that.
There's always the reflection option. Something substantially similar to this:
public static void Copy(object source, object target)
{
foreach (System.Reflection.PropertyInfo pi in source.GetType().GetProperties())
{
System.Reflection.PropertyInfo tpi = target.GetType().GetProperty(pi.Name);
if (tpi != null && tpi.PropertyType.IsAssignableFrom(pi.PropertyType))
{
tpi.SetValue(target, pi.GetValue(source, null), null);
}
}
}
Doesn't require the source and the target to have any relation what-so-ever, just a name and an IsAssignable check. It has the interesting side effects if you're using reference types anywhere, but for the kind of situation you just described, this isn't a bad option to explore.
class sourceTester
{
public bool Hello { get; set; }
public string World { get; set; }
public int Foo { get; set; }
public List<object> Bar { get; set; }
}
class targetTester
{
public int Hello {get; set;}
public string World { get; set; }
public double Foo { get; set; }
public List<object> Bar { get; set; }
}
static void Main(string[] args)
{
sourceTester src = new sourceTester {
Hello = true,
World = "Testing",
Foo = 123,
Bar = new List<object>()
};
targetTester tgt = new targetTester();
Copy(src, tgt);
//Immediate Window shows the following:
//tgt.Hello
//0
//tgt.World
//"Testing"
//tgt.Foo
//0.0
//tgt.Bar
//Count = 0
//src.Bar.GetHashCode()
//59129387
//tgt.Bar.GetHashCode()
//59129387
}

Categories