C# : AsQueryable() vs AsQueryable<type>() - c#

I am having problem while using AsQueryable, I found some example in which casting i.e. AsQueryable required for this extension and in some example directly as AsQueryable(). I check both case with Stopwatch and concluded with almost same result for multiple investigation.
Lets take example:
//With AsQueryable()
var studentId = dbContext.Students.AsQueryable().Where(a=>a.Name == "Abc").Select(a=>a.Id).FirstOrDefault();
//With AsQueryable<Student>()
var studentId = dbContext.Students.AsQueryable<Student>().Where(a=>a.Name == "Abc").Select(a=>a.Id).FirstOrDefault();
What is difference between using AsQueryable() and AsQueryable<type>() and which is efficient?

When you call AsQueryable() without specifying generic parameter type it's inferred by compiler from an object you call it at.
var source = new List<int>();
var queryable = source.AsQueryable(); // returns IQueryable<int>
is equivalent to
var queryable = source.AsQueryable<int>();
Update
To answer question asked in comments:
Then what is the use for having two different way? Is there any particular situation when we have to use only one of it?
Yes, you can't specify type parameter explicitly when using anonymous types, because you don't have class name:
source.Select((x,i) => new { Value = x, Index = i }).AsQueryable();
And that's exactly why type inference was introduced: to let you call generic methods without specifying type parameters when using anonymous types. But because it works not only with anonymous types, and saves you unnecessary typing, it's very common to rely on type inference whenever it's possible. That's why you'll probably see AsQueryable() without type parameter most of the times.

Whenever possible, the compiler can do type inference for you:
http://msdn.microsoft.com/en-us/library/twcad0zb.aspx
And in that case, there's no difference, advantage, or penalty either way. Type inference just makes your life easier and your code shorter.
However, I've run into cases when consuming APIs where a type implements several interfaces, e.g.
IEnumerable<IMySimpleThing>, IEnumerable<IMyComplexThing>, IEnumerable<MyComplexThing>
and type inference isn't sufficient if you're trying to get at a specific interface, e.g.
IEnumerable<MyComplexThing>
So in that case, specifying type to the generic, like .AsQueryable<MyComplexThing>(), will do the trick.

Related

Error when using a Linq Expression variable instead of lambda expression directly

I have the following code to get a collection of Types from an Assembly where the Type is a Class:
Assembly assembly = Assembly.LoadFile(DLLFile);
var types = assembly.GetTypes().AsEnumerable().Where(x => x.IsClass);
This works fine and as expected. However I wanted to pull out the lambda expression to a Linq Expression variable (as later on it will be used in a parameter of this method). So I did the following:
private Expression<Func<Type, bool>> _standardFilter = (x => x.IsClass);
Assembly assembly = Assembly.LoadFile(DLLFile);
var types = assembly.GetTypes().AsEnumerable().Where(_standardFilter);
However this won't compile with the error:
System.Collections.Generic.IEnumerable<System.Type>' does not contain a
definition for 'Where' and the best extension method overload
'System.Linq.Enumerable.Where<TSource>(System.Collections.Generic.IEnumerable<TSource>, System.Func<TSource,int,bool>)' has some invalid arguments
I understand that my expression doesn't conform to the predicate System.Func<TSource,int,bool>, however the Where function has an overload that takes a predicate of System.Func<TSource,bool>, which as far as I can tell should work.
I have tried converting the result of assembly.GetTypes() (which is an array) to a List in several ways without it helping the issue.
I have also made sure that I have got all the correct using statements for this class as that seems to be an issue several people run into during my Googling.
In the past I have managed to use this same technique on a IQueryable collection, but I don't understand why this won't work when the Where function is available on the IEnumerable collection and should accept the predicate I am providing.
Thanks very much for any assistance.
Compile your expression into executable code (delegate):
var types = assembly.GetTypes().AsEnumerable().Where(_standardFilter.Compile());
As #Kirk stated, it's better not to use expression tree, if you are not going to analyze it. Simply use filter of type Func<Type, bool>.
Note that the Enumerable extension method takes a Func, not an Expression. So your argument is incorrectly typed.
This is in contrast with Entity Framework, which takes Expression<Func> rather than plain Func.
So be attentive to method signatures, they are similar, can both be called with the same lambda, but are actually different!
The reason behind that is that EF inspects the Expression and converts it to SQL code, whereas Linq to Object simply executes the predicate in memory.
You could try this instead:
private Func<Type, bool> standardFilter;
standardFilter = (type) => {
return type.IsClass;
};
var types = assembly.GetTypes().AsEnumerable().Any(x => standardFilter(x));
Then you're free to change your implementation of standardFilter. As long as it takes in a Type and returns bool for whether or not that should be included it will remain modular and accomplish what I think you're going for.

Why VS2010 IntelliSense fails when chaining methods with dynamic args

I would like some explanation of you experts in C# 4.0 dynamic.
I have a fluent builder class to help configure an object before creating it. This interface has a method SetParameters(...):
public FluentBuilder<TInterface> SetParameters(dynamic parameters)
{
_parameters = parameters;
return this;
}
I'm doing this to consume the fluent interface:
var order = new Order();
/* Setting up parameters */
dynamic parameters = new ExpandoObject();
parameters.Transaction = transactionObj;
parameters.CurrentPrincipal = Thread.CurrentPrincipal;
var proxiedOrder = ObjectProxyFactory
.Configure<IOrder>(order)
.FilterMethods(o => o.InsertOrder())
.AddPreDecoration(AppConcerns.JoinSqlTransaction)
.AddPreDecoration(AppConcerns.EnterLog)
.AddPostDecoration(AppConcerns.ExitLog)
.AddPostDecoration(AppConcerns.SecurityCheck)
.SetParameters(parameters)
.Teste() //this method doesn't exist in the fluent builder
.CreateProxy();
var result = proxiedOrder.InsertOrder();
As commented in the above snippet, the method called Teste() doesn't exists in the fluent interface, but intelissense allow write anymethod after I call SetParameters like it returning dynamic, but as you see in code, SetParameters returns FluentInterface that is not dynamic.
The code above compiles sucessfully by in runtime will fail because in runtime the method Teste() will not be found in FluentBuilder class.
To resolve this problem in design-time, and to get correct Intelissense, I need to cast the parameter to the ExpandoObject class:
var proxiedOrder = ObjectProxyFactory
.Configure<IOrder>(order)
.FilterMethods(o => o.InsertOrder())
.AddPreDecoration(AppConcerns.JoinSqlTransaction)
.AddPreDecoration(AppConcerns.EnterLog)
.AddPostDecoration(AppConcerns.ExitLog)
.AddPostDecoration(AppConcerns.SecurityCheck)
.SetParameters((ExpandoObject)parameters) //cast to ExpandoObject
.Teste() //now intelissense is giving me an "red" error and solution will not compile
.CreateProxy();
var result = proxiedOrder.InsertOrder();
I've found that, anytime I pass a C# dynamic parameter in any method chaining, after that method receiving the dynamic parameter, the subsequent calls to methods will behave like returning a C# dynamic object, even if the return type of the method it's not dynamic.
Is it a bug ? Or is this expected to happens ?
It's expected to happen. Any method call involving a dynamic argument is resolved dynamically - the exact overload can't be determined until execution time, so the return type is unknown at compile time, so it's treated as being dynamic. In some cases the C# compiler could infer more information (e.g. if it's a static method call) but for simplicity it doesn't. Only a variable few expressions involving dynamic values have non-dynamic types. (From memory, the is operator is always bool, and a constructor is always assumed to return the type being constructed.)
EDIT: I've finally found the spec reference. From section 7.6.5:
An invocation-expression is dynamically bound (ยง7.2.2) if at least one of the following holds:
The primary-expression has compile-time type dynamic.
At least one argument of the optional argument-list has compile-time type dynamic and the primary-expression does not have a delegate type.
In this case the compiler classifies the invocation-expression as a value of type dynamic.

Why this is not possible in C# Generics?

A colleague pointed me to a strange case in C# (not so sure if this actually strange though).
Suppose you have a class Employee. If you want to create a Generic List<> of type Employee, you can simply do:
List<Employee> x = new List<Employee>;
I understand that I need to pass the Employee type to the Generic list so that it knows the required type information about Employee and generates methods that return and accept parameters that are compatible with Employee.
Now my question is, why isn't it possible to do the following?
Employee x = new Employee();
List<typeof(x)> list = new List<typeof(x)>();
Shouldn't this suffice the information required for List<> to know, in order to create a list? In other words, the type of x which is the type of Employee is now passed as a generic type parameter to List<>, which (as I used to believe) is the same as passing list the type name (in this case Employee).
I know that something like this is available in Java (using the .class) keyword on a variable.
I'm sure I AM missing something, so please, enlight me guys!
No, the equivalent of that isn't available in Java. You can't use "x.class" to get at the declared type of a variable.
Moreover, typeof(x) doesn't work in C# either to get the type of a variable - it returns a Type reference for the type name, e.g. typeof(string) will return a reference to the Type object associated with the System.String type. That's equivalent to using String.class in Java. (Note that again, that's applying .class to a type name, not a variable name.)
Java generics don't support anything like your final statement either. If you believe they do, please give a sample :)
What you can do in C# is use type inference to do what you want:
public static List<T> CreateListForSampleType<T>(T sample)
{
return new List<T>();
}
...
Employee x = new Employee();
var list = CreateListForSampleType(x);
Note that there's no reason why C# couldn't be extended to allow something like typeof(variablename) or List<typeof(variablename)> - it's all compile-time type information, after all. However, I can't see that it would meet the team's requirements for usefulness... there are other far more useful features I'd like to see first :)
The reason for this is that typeof() returns a type object, while you need a type name to initialize a list at compile-time.
One part of the answer is that the type of x is not available at compile time, i.e. it might be created using something like this:
Employee x = EmployeeFactory.NewEmployee("John Doe"); // Returns TraineeEmployee, Employee or ManagementEmployee;
List<typeof(x)> l = new List<typeof(x)> l(); // What type is it?
You can however create a List of a base class of what you want to store in the list (or even a List of "object"s).
typeof is used with class names. Use GetType() on an object, but only at runtime...
What you are missing - imho - is the difference between a static type reference at compile-time and a dinamyc type reference (via an instance of System.Type) at run-time.
typeof() and .GetType() give you the latter. (for types and instances, respectively)
I hope it makes clear.
Jon Skeet's code above is cool.
Can't find a reason to create an empty list since C# 3.0.
I generally create list instances only with a ToList method from an IEnumerable, which is in turn generated using a yield return, Concat(), Repeat(), Where() etc.
var list = CreateEmployees().ToList();
,
public IEnumerable<Employee> CreateEmployees()
{
yield return new Employee("Foo");
yield return new Employee("Bar");
}

How good is the C# type inference?

How good is C# type inference? I read somewhere that it's only for local variables? Does it work for class level attributes? For method signatures? Method return types? etc.
There are a few main kinds of type inference in C#:
Implicitly typed local variables:
Only for local variables
Only when the value is assigned as part of the declaration
Value cannot be null
Value cannot be a lambda expression, anonymous method or method group (without a cast)
The compile-time type of the value is used for the type of the variable
Any further uses of the variable are only checked against the type determined by the initial declaration+assignment; they don't contribute to the inference itself.
Generic method type argument inference, i.e. you don't specify the type arguments in a call to a generic method, the compiler figures them out based on the arguments.
Would be really handy to have this for generic types as well as generic methods
Really handy anyway - LINQ would be hard or impossible to use without it
Anonymous types would be fairly useless without it
Really complicated rules, even the spec is wrong in a few places
Lambda expression parameter type inference
Compiler tries to work out the types of the parameters for lambda expressions based on the context in which it's used
Usually works pretty well, in my experience
Array type inference, e.g. new[] { "Hi", "there" } instead of new string[] { "Hi", "there" }
Various small restrictions, nothing major
I've probably forgotten some other features which might be called "type inference". I suspect you're mostly interested in the first, but the others might be relevant to you too :)
It can only be used for local variables, but it can detect the type in many different forms.
var myVar = SomeMethodThatReturnsInt(); //will know it's an int
var myIntList = new List<int>(); //this works too (although this is technically not type inference)
var myOwnVar = new { Name = "John", Age = 100 }; // will create own type and infer that
EDIT: One more example of Tye Inference is with Lambdas. IE:
var myList = new List<int>();
//add some values to list
int x = myList.Find(i => i == 5); // compiler can infer that i is an int.
It works only with local variables as I understand it.

C# 3.0 Func/OrderBy type inference

So odd situation that I ran into today with OrderBy:
Func<SomeClass, int> orderByNumber =
currentClass =>
currentClass.SomeNumber;
Then:
someCollection.OrderBy(orderByNumber);
This is fine, but I was going to create a method instead because it might be usable somewhere else other than an orderBy.
private int ReturnNumber(SomeClass currentClass)
{
return currentClass.SomeNumber;
}
Now when I try to plug that into the OrderBy:
someCollection.OrderBy(ReturnNumber);
It can't infer the type like it can if I use a Func. Seems like to me they should be the same since the method itself is "strongly typed" like the Func.
Side Note: I realize I can do this:
Func<SomeClass, int> orderByNumber = ReturnNumber;
This could also be related to "return-type type inference" not working on Method Groups.
Essentially, in cases (like Where's predicate) where the generic parameters are only in input positions, method group conversion works fine. But in cases where the generic parameter is a return type (like Select or OrderBy projections), the compiler won't infer the appropriate delegate conversion.
ReturnNumber is not a method - instead, it represents a method group containing all methods with the name ReturnNumber but with potentially different arity-and-type signatures. There are some technical issues with figuring out which method in that method group you actually want in a very generic and works-every-time way. Obviously, the compiler could figure it out some, even most, of the time, but a decision was made that putting an algorithm into the compiler which would work only half the time was a bad idea.
The following works, however:
someCollection.OrderBy(new Func<SomeClass, int>(ReturnNumber))

Categories