How can i use generic list with foreach? - c#

if i compiled below codes error return foreach loop how can i solve it?
Error:Error 1 foreach statement cannot operate on variables of type 'Sortlist.MyCalısan' because 'Sortlist.MyCalısan' does not contain a public definition for 'GetEnumerator' C:\Users\yusuf.karatoprak\Desktop\ExcelToSql\TestExceltoSql\Sortlist\Program.cs 46 13 Sortlist
static void EskiMetodlaListele()
{
MyCalısan myCalısan = new MyCalısan();
Calısan calisan = new Calısan();
calisan.Ad = "ali";
calisan.SoyAd = "abdullah";
calisan.ID = 1;
myCalısan.list.Add(calisan);
foreach (Calısan item in myCalısan)
{
Console.WriteLine(item.Ad.ToString());
}
}
}
public class Calısan
{
public int ID { get; set; }
public string Ad { get; set; }
public string SoyAd { get; set; }
}
public class MyCalısan
{
public List<Calısan> list { get; set; }
public MyCalısan()
{
list = new List();
}
}

Only write foreach (Calısan item in myCalısan.list).

I recommend MyCalısan to define as Collection.
public class MyCalısan : Collection<Calısan>
{
}

You should loop on MyCalisan.list; MyCalisan is just your class, and is not enumerable itself.

a few issues need to be fixed before it will compile:
public class MyCalısan{
public List<Calısan> list { get; set; }
public MyCalısan()
{
list = new List<Calısan>();
}}
foreach (Calısan item in myCalısan.list)
{
Console.WriteLine(item.Ad.ToString());
}

You need to iterate over the collection you had defined - the list property:
myCalısan.list.Add(calısan);
foreach (Calısan item in myCalısan.list)
{
Console.WriteLine(item.Ad.ToString());
}
However, if you want to iterate over myCalısan directly, make the MyCalısan class implement IEnumerable<Calısan>.

Related

Issue with C# get and set properties for a List Collection

I need a seperate class where I want to add to some Lists anytime I set a new value. Using _name.Add(value) within the set method doesn't work.
I tried the following
public class XMLInformation
{
public String BusType
{
get
{
return SubBusType.LastOrDefault();
}
set
{
SubBusType.Add(value);
}
}
public List<string> SubBusType { get; set; }
}
I use it like this:
public STARC.GlobalVariables.XMLInformation XMLInformation = new STARC.GlobalVariables.XMLInformation();
XMLInformation.BusType = "Test";
now i get an error message (sorry error is partly in geeman)
ISSUE
What am I doing wrong?
It can solve your issue. List is not initialized and you are using it. so initialize it first and then use.
public class XMLInformation
{
public String BusType
{
get
{
return SubBusType == null ? null: SubBusType.LastOrDefault();
}
set
{
if (SubBusType == null)
SubBusType = new List<string>();
SubBusType.Add(value);
}
}
public List<string> SubBusType { get; set; }
}
Or
public class XMLInformation
{
public String BusType
{
get
{
return SubBusType.LastOrDefault();
}
set
{
SubBusType.Add(value);
}
}
public List<string> SubBusType { get; set; } = new List<string>();
}
You have to Initialize the SubBusType object because at starting it will be null.
You can do either by creating in the constructor like below
public XMLInformation()
{
SubBusType = new List<string>();
}
or initiate on declaring the SubType itself like below.
public List<string> SubBusType { get; set; } = new List<string>();

C# foreach loop thru collection of unknown type

I have a generic method that can be called with 2 different object types, TypeA or TypeB. TypeA and TypeB are essentially identical classes except in name only. I am trying to determine how to prevent from having to duplicate the Foreach loop code for each object type. Is this possible ? thanks.
public class TypeA
{
public string Name { get; set; }
public string Department { get; set; }
public string Total { get; set; }
}
public class TypeB
{
public string Name { get; set; }
public string Department { get; set; }
public string Total { get; set; }
}
private CsvExport GenerateExport<T>(IEnumerable<T> scores)
{
CsvExport export = new CsvExport();
List<TypeA> aList = null;
List<TypeB> bList = null;
Type type = scores.GetType();
if (type.FullName.Contains("TypeA"))
{
aList = scores as List<ObjectaModel>;
}
else if (type.FullName.Contains("TypeB"))
{
bList = scores as List<ObjectbModel>;
}
foreach (var dt in aList)
{
export.AddRow();
export["Name"] = dt.Name;
export["Department"] = dt.Department;
export["Total "] = dt.Total;
};
return export;
}
In this particular case I strongly suggest you delegate the hard work to the CsvHelper library which you can also obtain from Nuget and is used like this...
public void ExportToCsv<T>(string filename, ImmutableArray<T> objects)
{
using (var writer = File.CreateText(filename))
{
var csv = new CsvWriter(writer);
csv.WriteRecords(objects);
}
}
The more general answer to your question is that you must either have both classes inherit from a common class or interface or you would have to use reflection to look for an obtain the values of the named properties.
Using a common interface...
public interface IScore
{
int HiScore {get;}
}
public class ScrabbleScore : IScore
{
public int HiScore {get;set;}
}
public class PacManScore : IScore
{
public int HiScore {get;set;}
}
public void Export<T>(IEnumerable<T> scores) where T: IScore
{
foreach(var s in scores)
{
CvsExport["Hi score"]= s.HiScore;
}
}
Using reflection...
var CsvExport = new Dictionary<string,string>();
foreach(var o in scores)
{
//note that checking the type for each object enables you to have heterogenous lists if you want
var objectType= o.GetType();
foreach(var p in objectType.GetProperties())
{
var propertyName = p.Name;
CsvExport[propertyName] = p.GetValue(o).ToString();
}
}
I would treat the reflection solution as the least favoured of the three.

Sort MultiLevel Data with Linq

I have a data structure as follows:
public class BranchLevel_1
{
public string Name { get; set; }
public ObservableCollection<BranchLevel_2> Children { get; set; }
public BranchLevel_1(string name, List<BranchLevel_2> children)
{
this.Name = name;
this.Children = new ObservableCollection<BranchLevel_2>(children);
}
}
public class BranchLevel_2
{
public ObservableCollection<BranchLevel_3> Contents { get; set; }
public BranchLevel_2(List<string> contents)
{
this.Contents = new ObservableCollection<BranchLevel_3>();
for (int i = 0; i < contents.Count; i++)
{
this.Contents.Add(new BranchLevel_3(contents[i]));
}
}
}
public class BranchLevel_3
{
public string Content { get; set; }
public BranchLevel_3(string text)
{
this.Content = text;
}
}
Sorting data on the first level is easy and I can obtain in easily by:
Level1_Data.OrderBy(item => item.Name).ToList()
However, I am stuck with sorting on the second level. BranchLevel_2 class is just a container for items stored in BranchLevel_3 classes. Therefore I would like to sort Level2 with data stored in BranchLevel_2.Contents1.Content value. This syntax for me seems to be correct and I cannot locate the problem...
Level1_Data.Select(item_Level1 => item_Level1.Children.OrderBy(item_Level2 => item_Level2.Contents[1].Content)).ToList();
Any hints?
Here is the rusult (indicated in yellow is supposed to be sorted alphabetically)
Why not just sort the contents before adding them to the ObservableCollection
public class BranchLevel_2
{
public ObservableCollection<BranchLevel_3> Contents { get; set; }
public BranchLevel_2(List<string> contents)
{
this.Contents = new ObservableCollection<BranchLevel_3>();
foreach (var content in contents.OrderBy(c => c))
{
this.Contents.Add(new BranchLevel_3(content));
}
}
}
Here is a solution that solved the problem, thanks to suggestion from #bhmahler
public class BranchLevel_1
{
public string Name { get; set; }
public ObservableCollection<BranchLevel_2> Children { get; set; }
public BranchLevel_1(string name, List<BranchLevel_2> children)
{
this.Name = name;
//this line needs to be added before creating ObservableCollection
children.OrderBy(item_level2 => item_level2.Contents[1].Content).ToList();
this.Children = new ObservableCollection<BranchLevel_2>(children);
}
}

Type Casting Exception With Inheritance

Here is my code below. It gives me Casting exception problem at selIngs.Add(da). tried with the 2nd way. it still give me the same exception. I wonder where I am doing wrong? Once I implement the interface or inherit the base class it should be ok to treat child class as the same. Any idea please?
//1st way
public interface IngredientInterface
{
double Concentration { get; set; }
string DateCreated { get; set; }
string DevCode { get; set; }
}
public class IngredientData : INotifyPropertyChanged, IngredientInterface
{
public string GroupCode
{
get { return groupCode; }
set
{
groupCode = value;
}
}
public double Setpoint { get; set; }
public bool IsHighlighted { get; set; }
public double PPT { get; set; }
}
public class FormulaUploadViewModelData: IngredientData
{
//.....
}
public class FormulaUploadViewModel :INotifyPropertyChanged
{
public FormulaUploadViewModel()
{
selIngs = new List<FormulaUploadViewModelData>();
}
private void IngsUp()
{
List<IngredientData> someIngData = new List<IngredientData>();
foreach (FormulaUploadViewModelData da in someIngData)
{
selIngs.Add(da); //here gives me casting exception
}
}
}
//2nd way
public class FormulaUploadViewModelData: IngredientInterface
{
//.....
}
public class FormulaUploadViewModel :INotifyPropertyChanged
{
public FormulaUploadViewModel()
{
selIngs = new List<FormulaUploadViewModelData>();
}
private void IngsUp()
{
List<IngredientInterface> someIngData = new List<IngredientInterface>();
foreach (FormulaUploadViewModelData da in someIngData)
{
selIngs.Add(da); //here gives me casting exception
}
}
}
All FormulaUploadViewModelData are IngredientInterface. So this will work:
var ingredients = new List<IngredientInterface>();
ingredients.Add(new FormulaUploadViewModelData());
But the opposite does not work because not all IngredientInterface are FormulaUploadViewModelData which is what should follow from allowing:
var formulas = new
List<FormulaUploadViewModelData>();
formulas(someIngredientInterface);
Solution? Make sure the da you are adding is in fact a FormulaUploadViewModelData. There is quite a few ways to do it, to name a couple:
Pattern matching
foreach (var da in someInData)
if (da is FormulaUploadViewModelData formula)
selIngs.Add(formula)
Use Enumerable.OfType<> extension method
foreach (var formula in
someInData.OfType<FormulaUploadViewModelData>())
selIngs.Add(formula)
Etc.

How to loop through List<dynamic>

I have a Class which contains a dynamic List, which I manage to access like this.
foreach (var c in objects)
{
foreach (dynamic i in c.data)
{
var ss = i;
}
}
The Class
public class iUpdateGrid
{
public int type { get; set; }
public string session { get; set; }
public string latitude { get; set; }
public string longitude { get; set; }
public string ip { get; set; }
public int id { get; set; }
public string station { get; set; }
public List<iGridData> h_33 { get; set; }
}
public class iGridData
{
public string table { get; set; }
public List<dynamic> data { get; set; }
}
"ss" contains now a list of objects, however have no idea how to get these values to a Dictionary or list.
One note I also need to adjust the key names.
Things I tried to do:
foreach (KeyValuePair<string, string> kv in i)
{
string key = kv.Key;
string value = kv.Value;
}
foreach statement cannot operate on variables of type 'System.Collections.IEnumerable' because 'System.Collections.IEnumerable' does not contain a public definition for 'GetEnumerator'
Also the Dynamic objects does not give me the options to access the key and/or value.
Any help how I can loop through this would be very welcome.
also when I put this on runtime "i" says its a System.Collections.Generic.Dictionary however can access this also.
Solution:
Made little chance to solution as provided, but this worked for me:
foreach (var c in objects)
{
foreach (dynamic i in c.data)
{
foreach (var v in (i as IDictionary<string, object>))
{
string key = v.Key;
object value = v.Value;
}
}
}
foreach (var v in (i as IEnumerable<object>))
{
if (v is KeyValuePair<string, string>)
{
// Do stuff
}
else if (v is List<string>)
{
//Do stuff
}
else throw new InvalidOperationException();
}
foreach (var c in objects)
{
foreach (dynamic i in c.data)
{
var property_value = i.GetType().GetProperty("PROPERTY_NAME").GetValue(i);
}
}

Categories