What does var really do in the following case?
var productInfos =
from p in products
select new { p.ProductName, p.Category, Price = p.UnitPrice };
The two lines:
var productInfos = from p in products
select new { p.ProductName, p.Category, Price = p.UnitPrice };
and
IEnumerable<CompilerGeneratedType> productInfos = from p in products
select new { p.ProductName, p.Category, Price = p.UnitPrice };
are equivalent. CompilerGeneratedType is a type that will be created by the compiler and has the three public properties ProductName, Price, and Category. var is helpful for two reasons:
CompilerGeneratedType will be generated by the compiler so it's impossible for you to use the type name in the declaration.
You don't have to think too hard about the collection type of the result. Linq can do its thing and you don't have to worry about it.
var is a placeholder for a compiler-created ("anonymous") type that has three properties, ProductName, Category and Price.
It is NOT a variant (e.g. as in Visual Basic). It is a concrete type and can be used as such in other places in the code.
In this particular case, the type of productInfos is a compiler-generated Anonymous Type with 3 properties, ProductName, Category and Price.
variables with var are implicitly typed local variable which are strongly typed just as if you had declared the type yourself, but the compiler determines the type. it gets the type of the result.
and here a nice read C# Debate: When Should You Use var?
and here another C# 3.0 Tutorial
var = programmer friendly = less typing = makes you lazy(another way of looking at it) = brings obscurity to code if new to 3.5 FW
It eases you from the pain of having to declare the exact type of your query result manually. But I have to empathize, this is not dynamic typing: the productInfos variable will have a static type, but it is created by the compiler instead of you.
Related
I try to find some references on LINQ with dynamic added strong types, static I have as in example:
var rowColl = _data.AsEnumerable();
var json = (from r in rowColl
select new
{
name = r.Field<string>("name"),
id = r.Field<int>("id"),
}).ToList();
Now where I am interested in if its possible to make "name" and "id" dynamic added on runtime as the information is available in the DataTable "_data", I think there is a simple solution for this however cant find any references on this
It's better practice to avoid using "var" as your type when possible. It looks like rowColl is of type IEnumerable<DataRow>. If that's true, then I would look to see what you can use in the DataRow class (see msdn documentation).
Given that rowColl is actually IEnumerable<DataRow>... If the columns are always going to be in the same order, then you could just do something like r[0] and r[1] in your select statement, i.e.
var json = (from r in rowColl
select new
{
name = r[0], // Where 0 is the index of the "name" column
id = r[1],
}).ToList();
If it complains at you for type-safety, then you could use int.Parse() to cast the string to an int and use the .ToString() extension on your columns instead.
I have List where MyType : DynamicObject. The reason for MyType inheriting from DynamicObject, is that I need a type that can contain unknown number of properties.
It all works fine until I need to filter List. Is there a way I can do a linq that will do something like this:
return all items where any of the properties is empty string or white space?
(from the comment) can I do above linq query with List?
Yes, here is how you can do it with ExpandoObject:
var list = new List<ExpandoObject>();
dynamic e1 = new ExpandoObject();
e1.a = null;
e1.b = "";
dynamic e2 = new ExpandoObject();
e2.x = "xxx";
e2.y = 123;
list.Add(e1);
list.Add(e2);
var res = list.Where(
item => item.Any(p => p.Value == null || (p.Value is string && string.IsNullOrEmpty((string)p.Value)))
);
The ExpandoObject presents an interface that lets you enumerate its property-value pairs as if they were in a dictionary, making the process of checking them a lot simpler.
Well as long as each object's properties are not unknown internally to themselves you could do it.
There isn't a great generic way to test all the properties of a dynamic object, if you don't have control over the DynamicObject you hope the implementer implemented GetDynamicMemberNames() and you can use the nuget package ImpromptuInterface's methods for getting the property names and dynamically invoking those names.
return allItems.Where(x=> Impromptu.GetMemberNames(x, dynamicOnly:true)
.Any(y=>String.IsNullOrWhiteSpace(Impromptu.InvokeGet(x,y));
Otherwise, since it's your own type MyType you can add your own method that can see internal accounting for those member values.
return allItems.Where(x => x.MyValues.Any(y=>String.IsNullOrWhitespace(x));
When is it required to use new in the select clause as in the following example? Thanks.
var results = from person in people
select new { FN = person.FirstName, LN = person.LastName };
I've searched and partially understand this: "In the select new, we're creating a new anonymous type with only the properties you need." But does it mean I can omit new and not get an anonymous type?
To restate my question in another way: is 'new' optional? Is 'new' here similar to C# new where it is not required with value type?
Can I do this?
var results = from person in people
select { FN = person.FirstName, LN = person.LastName };
No, new is not optional if you're selecting "new" objects. (which is what you are doing. You are creating new objects of an anonymous type with 2 properties FN and LN)
Simply omitting new is a syntax error.
If you have an existing type you would like to use, (say you've defined a class Person with 2 properties FN and LN) then you can use that type. E.g.
var results = from person in people
select new Person { FN = person.FirstName, LN = person.LastName };
(assuming Person has a parameterless constructor and FN and LN are properties with setters)
The only time you can omit new is if you are not creating a new object, for instance:
var results = from person in people
select LN = person.LastName;
There you are selecting just the LastName and the result is an IEnumerable<string>
If you are projecting to a new type (anonymous class or known class/struct) it is not optional but required.
If you are projecting to an existing instance though of course you don't need the new, i.e. in your example if you just wanted to project to the first name of each person (to get a string enumeration you could just do:
var results = from person in people select person.FirstName
So rule of thumb if you are constructing a new type you need new in the projection (Select), if you are just selecting something that already exists you don't.
Instead of creating an anonymous type you can instantiate an instance of a named type that takes a Person as an argument or assign values using the object initializer syntax.
Example:
var results = from person in people
select new Report(person);
var results = from person in people
select new Report() { Customer = person };
Edit: Or of course just select a single property from the person object as BrokenGlass pointed out!
Edit: I just re-read your question and wanted to point out that anonymous types in C# are just normal types with the type name generated by the compiler. So yes, you still need to use the new operator because you're creating a new instance of a type. Anonymous Types (C# Programming Guide)
need help
I have this enum which sets the PayClassNo to Direct and Indirect. I want to use this enum in my LinQ query.
Here's my scratch LinQ query:
var jDef = from jd in context.GetTable<RJVDefinition>()
select new PayrollJVDefinition
{
JVdefNo = jd.JVDefNo,
AccntCode = jd.AccntCode,
AccntDesc = jd.AccntDesc,
PayClass = enum.GetValue(jd.PayClassNo),
IsFixed = jd.IsFixed,
IsEmployee = jd.IsFixed,
IsAR = jd.IsAR,
CreatedByNo = jd.CreatedByNo,
CreatedDate = jd.CreatedDate,
ModifiedByNo = jd.ModifiedByNo,
ModifiedDate = jd.ModifiedDate
};
Need help because I'm not sure if this will work.
You could certainly do the translation in code, similar to your example (using Enum.Parse), but you don't need to. You can use the designer to set the object property type to an enumerated value. See this article for details.
You just need to parse the Enum just use something like
Enum.Parse(jb.PayClassNo, YourEnumType)
The main problem is that I recieve the following message:
"base {System.SystemException} = {"Unable to create a constant value of type 'BokButik1.Models.Book-Author'. Only primitive types ('such as Int32, String, and Guid') are supported in this context."}"
based on this LinQ code:
IBookRepository myIBookRepository = new BookRepository();
var allBooks = myIBookRepository.HamtaAllaBocker();
IBok_ForfattareRepository myIBok_ForfattareRepository = new Bok_ForfattareRepository();
var Book-Authors =
myIBok_ForfattareRepository.HamtaAllaBok_ForfattareNummer();
var q =
from booknn in allBooks
join Book-Authornn in Book-Authors on booknn.BookID equals
Book-Authornn.BookID
select new { booknn.title, Book-AuthorID };
How shall I solve this problem to get a class instance that contain with property title and Book-AuthorID?
// Fullmetalboy
I also have tried making some dummy by using "allbooks" relation with Code Samples from the address http://www.hookedonlinq.com/JoinOperator.ashx. Unfortunately, still same problem.
I also have taken account to Int32 due to entity framework http://msdn.microsoft.com/en-us/library/bb896317.aspx. Unfortunatley, still same problem.
Using database with 3 tables and one of them is a many to many relationship. This database is used in relation with entity framework
Book-Author
Book-Author (int)
BookID (int)
Forfattare (int)
Book
BookID (int)
title (string)
etc etc etc
It appears that you are using two separate linq-to-sql repositories to join against. This won't work. Joins can only work between tables defined in a single repository.
However, if you are happy to bring all of the data into memory then it is very easy to make your code work. Try this:
var myIBookRepository = new BookRepository();
var myIBok_ForfattareRepository = new Bok_ForfattareRepository();
var allBooks =
myIBookRepository.HamtaAllaBocker().ToArray();
var Book_Authors =
myIBok_ForfattareRepository.HamtaAllaBok_ForfattareNummer().ToArray();
var q =
from booknn in allBooks
join Book_Authornn in Book_Authors
on booknn.BookID equals Book_Authornn.BookID
select new { booknn.title, Book_AuthorID = Book_Authornn.Book_Author };
Note the inclusion of the two .ToArray() calls.
I had to fix some of you variable names and I made a bit of a guess on getting the Author ID.
Does this work for you?
I would suggest only having a single repository and allowing normal joining to occur - loading all objects into memory can be expensive.
If you are making custom repositories you make also consider making a custom method that returns the title and author IDs as a defined class rather than as anonymous classes. Makes for better testability.