Initialize a List<T> with inline definition of <T> - c#

You can always define a class like this:
public class item {
int id;
string name;
}
and then use it like this:
List<item> items = new List<item>();
Can we not do something like this:
var items = new List<{int id, string name}>();
Just a short way of initializing when underlying object definition is simple and predictable.
This is possible in JavaScript (I have seen examples in Angular).
Sorry if this is answered before, my quick search could not find an answer to this specific topic on Google or SO.

C# 7 introduces tuples, so you can do this:
var list = new List<(int id, string name)>();
list.Add((3, "Bob"));
var (id, name) = list[0];
var entry = list[0];
string s = $"{entry.name} has ID {entry.id}";
foreach (var (id, name) in list)
{
}
Before C# 7 you can use the old Tuple type, which is a bit more messy:
var list = new List<Tuple<int, string>>();
list.Add(Tuple.Create(3, "Bob"));
foreach (var item in list)
{
int id = item.Item1;
string name = item.Item2;
}

In c# 7.0 and higher you can use value tuples - the syntax is almost identical:
var items = new List<(int id, string name)>();

Also you can do it like this:
var list = new[] { new { Id = 1, Name = "name" } }.ToList();
list.Add(new { Id = 2, Name = "name2" });
foreach (var item in list)
{
int id = item.Id;
string name = item.Name;
}
References: Anonymous Types, Implicitly Typed Arrays, ToList Extension Method

Related

Why is the return is List<char>?

I am trying to pull file names that match the substring using "contains" method. However, return seem to be List<char> but I expect List<string>.
private void readAllAttribues()
{
using (var reader = new StreamReader(attribute_file))
{
//List<string> AllLines = new List<string>();
List<FileNameAttributeList> AllAttributes = new List<FileNameAttributeList>();
while (!reader.EndOfStream)
{
FileNameAttributeList Attributes = new FileNameAttributeList();
Attributes ImageAttributes = new Attributes();
Point XY = new Point();
string lineItem = reader.ReadLine();
//AllLines.Add(lineItem);
var values = lineItem.Split(',');
Attributes.ImageFileName = values[1];
XY.X = Convert.ToInt16(values[3]);
XY.Y = Convert.ToInt16(values[4]);
ImageAttributes.Location = XY;
ImageAttributes.Radius = Convert.ToInt16(values[5]);
ImageAttributes.Area = Convert.ToInt16(values[6]);
AllAttributes.Add(Attributes);
}
List<string> unique_raw_filenames = AllAttributes.Where(x => x.ImageFileName.Contains(#"non")).FirstOrDefault().ImageFileName.ToList();
List<string>var unique_reference_filenames = AllAttributes.Where(x => x.ImageFileName.Contains(#"ref")).FirstOrDefault().ImageFileName.ToList();
foreach (var unique_raw_filename in unique_raw_filenames)
{
var raw_attributes = AllAttributes.Where(x => x.ImageFileName == unique_raw_filename).ToList();
}
}
}
Datatype class
public class FileNameAttributeList
{ // Do not change the order
public string ImageFileName { get; set; }
public List<Attributes> Attributes { get; set; }
public FileNameAttributeList()
{
Attributes = new List<Attributes>();
}
}
Why is FirstOrDefault() does not work ? (It returns List<char> but I am expecting List<string> and fails.
The ToList() method converts collections that implement IEnumerable<SomeType> into lists.
Looking at the definition of String, you can see that it implements IEnumerable<Char>, and so ImageFileName.ToList() in the following code will return a List<char>.
AllAttributes.Where(x =>
x.ImageFileName.Contains(#"non")).FirstOrDefault().ImageFileName.ToList();
Although I'm guessing at what you want, it seems like you want to filter AllAttributes based on the ImageFileName, and then get a list of those file names. If that's the case, you can use something like this:
var unique_raw_filenames = AllAttributes.Where(x => x.ImageFileName.Contains(#"non")).Select(y=>y.ImageFileName).ToList();
In your code
List<string> unique_raw_filenames = AllAttributes.Where(x => x.ImageFileName.Contains(#"non")).FirstOrDefault().ImageFileName.ToList();
FirstOrDefault() returns the first, or default, FileNameAttributeList from the list AllAttributes where the ImageFileName contains the text non.
Calling ToList() on the ImageFileName then converts the string value into a list of chars because string is a collection of char.
I think that what you are intending can be achieved by switching out FirstOrDefault to Select. Select allows you to map one value onto another.
So your code could look like this instead.
List<string> unique_raw_filenames = AllAttributes.Where(x => x.ImageFileName.Contains(#"non")).Select(x => x.ImageFileName).ToList();
This then gives you a list of string.

How to select specific fields from dynamic list using LINQ

I am trying to get the some specific fields from dynamic object with is actually a list of any class, this class contains various fields out of those fields I want to select some specific fields using LINQ, The fields which I want to select is also passing by the user. Below is the code that I have tried using System.Linq.Dynamic.
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Linq.Dynamic;
using System.Collections;
private void Test_Click(object sender, EventArgs e)
{
List<RateInfo> lst = new List<RateInfo>();
lst.Add(new RateInfo() { id_country = "IND", id_state = 1, rate = 2.3f });
lst.Add(new RateInfo() { id_country = "IND", id_state = 2, rate = 1.1f });
lst.Add(new RateInfo() { id_country = "IND", id_state = 3, rate = 5.2f });
lst.Add(new RateInfo() { id_country = "IND", id_state = 4, rate = 6.5f });
GetDynamicData(lst, new List<string>() { "id_country", "id_state" });
}
private void GetDynamicData(dynamic list, List<string> fetchFields)
{
var data = ((IEnumerable)list).Cast<dynamic>()
.Select(r => new { r }).AsQueryable();
StringBuilder s = new StringBuilder();
//This is for test only.
//It works, the value of "id_state" and "id_state" getting appended
foreach (var item in data)
{
s.Append(item.r.id_state);
s.Append(",");
s.Append(item.r.id_country);
}
//-----------------------------------------------------
//Select the specific field data from dynamic list
StringBuilder fields = new StringBuilder();
fields.Append("new (");
foreach (var fld in fetchFields)
{
fields.Append("r." + fld);
fields.Append(",");
}
fields.Remove(fields.Length - 1, 1);
fields.Append(")");
//This does not work throws error
//"No property or field 'id_country' exists in type 'Object'"
IQueryable iq = data.Select(fields.ToString());
//For test only to check the value of selected fields
foreach (dynamic item in iq)
{
s.Append(item.id_state);
s.Append(",");
s.Append(item.id_country);
}
}
you can hughly simplify your GetDynamicData method both specifying explicit list type (GetDynamicData(IList<RateInfo> list, ...)) and leaving the list item type generic, in order to reuse the method; with this last approach in mind, you can rewrite the GetDynamicData as follows, obtaining the desired output:
private void GetDynamicData<T>(IEnumerable<T> list, List<string> fetchFields)
{
var fields = $"new ({string.Join(",", fetchFields)})";
var res = list.AsQueryable().Select(fields);
//For test only to check the value of selected fields
foreach (dynamic item in res) {
Console.WriteLine(item.id_state);
Console.WriteLine(item.id_country);
}
}
OUTPUT
1
IND
2
IND
3
IND
4
IND
EXPLANATION
I think the difference is that specifying explicitly the type (through generic T or through RateInfo) you force LINQ to know list items'type; if you use dynamic the IQueryable.ElementType of the IQuqryable instance has value System.Object, so the query fails with the error you've experienced.
You should try using generics:
private void GetDynamicData<T>(IEnumerable<T> list, List<string> fetchFields)
{
var data = list.AsQueryable();

How to get all the values from an SQL Query C#

I have used String Builder to generate a RAW SQL QUERY in C#.
List<string> columns = new List<string>();
columns.Add("id");
columns.Add("Temp");
StringBuilder SqlStatement = new StringBuilder();
SqlStatement.Append("Select ");
for (int i = 0; i < columns.Count; i++)
{
if (i == columns.Count - 1)
{
SqlStatement.Append(columns[i]);
}
else
{
SqlStatement.Append(columns[i]);
SqlStatement.Append(",");
}
}
SqlStatement.Append(" FROM graph_update");
var ctx = new graphDBContext();
var result = ctx.Database.SqlQuery<graphDBContext>(SqlStatement.ToString()).ToList();
This translates into SELECT id,Temp FROM graph_update
And the result gives me
id = 1, temp = 20
id = 2 temp = 30
How do I get all these values????
I'm too use to:
foreach(var item in result)
{
item.id = id;
item.temp = temp;
}
But it won't let me.
EDIT:
Sorry but I'm not sure what you mean. Here is my debugger
Try to use foreach like this if theres no error return
foreach(var v in result)
{
String v0 = v[0].ToString();
String v1 = v[1].ToString();
}
Assuming you have EF > 6, then the ctx.Database.SqlQuery, according to the method documentation:
Creates a raw SQL query that will return elements of the given generic type.
The type can be any type that has properties that match the names of the columns returned from the query, or can be a simple primitive type. The type does not have to be an entity type. The results of this query are never tracked by the context even if the type of object returned is an entity type.
With that in mind you can do something like this:
public class GraphUpdateResult
{
public int Id {get; set;}
public decimal Temp {get; set;}
}
Then in your current method:
var result = ctx.Database.SqlQuery<GraphUpdateResult>SqlStatement.ToString()).ToList();
foreach (var graphResult in result)
{
Console.WriteLine(graphResult.Id);
Console.WriteLine(graphResult.Temp);
}
You can add more columns to the GraphUpdateResult class for EF to bind to, even if in some queries you don't specify them in the select statement.
I hope this helps.
foreach(var item in result)
{
var id = item.id;
var temp = item.temp;
}
in your code above, you are trying to assign the values to the item, instead of retrieving.
You can use a ORM-Mapper like
https://stormy.codeplex.com/SourceControl/latest#Stormy.cs
It is a very light Mapper and you can look how it works.
It maps the reader Data to the Object data:
public class CatMapper : ISelectable<Cat>
{
public Cat ApplySelect(IDataReader reader)
{
return new Cat()
{
Name = reader["name"].ToString(),
Weight = (float)reader["weight"]
};
}
}

How to iterate through IEnumerable collection using for each or foreach?

I want to add one by one values but in for loop how can I iterate
through one by one values and add it inside dictionary.
IEnumerable<Customer> items = new Customer[]
{
new Customer { Name = "test1", Id = 111},
new Customer { Name = "test2", Id = 222}
};
I want to add { Name = "test1", Id = 111} when i=0
and want to add { Name = "test2", Id = 222} when i=1 n so on..
Right now i'm adding full collection in every key.(want to achieve this using foreach or forloop)
public async void Set(IEnumerable collection)
{
RedisDictionary<object,IEnumerable <T>> dictionary = new RedisDictionary>(Settings, typeof(T).Name);
// Add collection to dictionary;
for (int i = 0; i < collection.Count(); i++)
{
await dictionary.Set(new[] { new KeyValuePair<object,IEnumerable <T> ( i ,collection) });
}
}
If the count is need and the IEnumerable is to be maintained, then you can try this:
int count = 0;
var enumeratedCollection = collection.GetEnumerator();
while(enumeratedCollection.MoveNext())
{
count++;
await dictionary.Set(new[] { new KeyValuePair<object,T>( count,enumeratedCollection.Current) });
}
New version
var dictionary = items.Zip(Enumerable.Range(1, int.MaxValue - 1), (o, i) => new { Index = i, Customer = (object)o });
By the way, dictionary is a bad name for some variable.
I'm done using
string propertyName = "Id";
Type type = typeof(T);
var prop = type.GetProperty(propertyName);
foreach (var item in collection)
{
await dictionary.Set(new[] { new KeyValuePair<object, T>(prop.GetValue(item, null),item) });
}
So you want to a an item from the collection to the dictionary in the for loop?
If you cast your IEnumerable to a list or an array, you can easily access it via the index. For example like this:
Edit: Code at first created a list every time it looped, which should of course be avoided.
var list = collection.ToList(); //ToArray() also possible
for (int i = 0; i < list.Count(); i++)
{
dictionary.Add(i, list[i]);
}
I'm not 100% if that is what you need, though. More details to your question would be great.

Filtering a list in c#

So i have two lists .One is an Attorney object list and the other is a list with GUID .I am first just filling the GUID list with values and then looping through it and then matching it to the ID field of Attorney object to get the Attorney's with the given ID .
Is there a nicer way than my try to achieve this.
List<Attorney> Attorneys = msg.CaseDocument.Attorneys;
List<Attorney> CaseDefendantAtt = new List<Attorney>();
List<Guid> AttorneyID = new List<Guid>();
foreach (var s in msg.CaseDocument.Defendants)
{
AttorneyID.AddRange(s.Attorneys);
}
foreach (var p in AttorneyID)
{
var z = Attorneys.FindAll(o => o.AttorneyId == p);
if (z != null)
{
CaseDefendantAtt.AddRange(z);
}
}
How about...
var caseDefendantAtt = msg.CaseDocument.Attorneys.Where(o =>
msg.CaseDocument.Defendants.SelectMany(d => d.Attorneys).Contains(o.AttorneyId));
Try this
var allAttorneyIds = msg.CaseDocument.Defendants.SelectMany(x=> x.Attroneys);
var caseDefendantsAtt = msg.CaseDocument.Attorneys.Where(x=> allAttorneyIds.Contains(x.AttorneyId)).ToList();
Maybe you could store your Attorneys in a Dictionary of [Guid, Attorney], then looking for each Guid in Dictionary.
Dictionary<Guid, Attorney> Attorneys = CreateDictionaryFrom(msg.CaseDocument.Attorneys);
List<Attorney> CaseDefendantAtt = new List<Attorney>();
List<Guid> AttorneyID = new List<Guid>();
foreach (var s in msg.CaseDocument.Defendants)
{
AttorneyID.AddRange(s.Attorneys);
}
foreach (var p in AttorneyID)
{
var z = Attorneys[p];
if (z != null)
{
CaseDefendantAtt.Add(z);
}
}
It will increase the performance with the x1000 factor. But you should notice that we assume there is only one attorney per Guid.
Without using a dictionary, we could improve your search in list seeking for FirstOrDefault instead of FindAll

Categories