Can I achieve covariance in .NET 3.5, C# - c#

I have class X that implements an interface IX. I also have a repository class dedicated for X, which uses lambda expresions as parameters:
public interface IX
{
}
public class X : IX
{
....
}
public class XRepository : IRepository<X>
{
public IEnumerable<X> Filter(Func<X, bool> filterFunc)
{
...
}
}
I need to make the repository class work with the interface IX, therefore I add IRepository<IX> to the interfaces being implemented:
public class XRepository : IRepository<X>, IRepository<IX>
{
public IEnumerable<X> Filter(Func<X, bool> filterFunc)
{
...
}
public IEnumerable<IX> Filter(Func<IX, bool> filterFunc)
{
// I need to call the same filter method as above, but
// in order to do so I must convert the Func<IX, bool> to Func<X, bool>.
}
}
I must convert the Func<IX, bool> to Func<X, bool>, but since the code is written in C# 3.0 using .NET 3.5, I cannot benefit from Type covariance, which was introduced in 4.0.
A simple solution could be to use Func<X, bool> newFunc = x => filterFunc(x);, where filterFunc is of type Func<IX, bool>. This would compile and one might expect it to run fine, but I assume it will not. The problem is that I am using 3rd party framework for the filter implementation, namely FluentNhibernate. I know it uses expression trees to strip the passed into the lambda expression member access condition (like x => x.Name == "John") in order to build native SQL query (like WHERE Name = 'John'). The above solution would produce a Func<X, bool> that is not such expression and I fear it will fail to translate. So I need to create the same lambda expression but with the compatible type. Knowing that X implements IX, it is obvious that any code inside a Func<IX, bool> will work for objects of type X. It is not obvious for me, however, how can I perform this conversion.
I assume this can be done using expression trees. I also fear my performance will suffer greatly. Even if I decide to have another solution to my scenario, I will still appreciate the suggested way to translate one lambda into a similar another.
Edit:
To clarify more about the issue I am experiencing, I wrote the following test, simulating the real-life scenarion I am facing:
Func<IX, bool> filter = y => y.Name == "John";
Func<X, bool> compatibleFilter = y => filter(y);
...
// Inside the Filter(Func<X, bool> filter method)
using(var session = nhibernateSessionFactory.OpenSession())
{
IEnumerable<X> xx = session.Query<X>().Where(z => compatibleFilter(z)).ToList();
}
so, at the ToList() method I receive the following exception
Unable to cast object of type 'NHibernate.Hql.Ast.HqlParameter' to type 'NHibernate.Hql.Ast.HqlBooleanExpression'.
This confirms my assumption that Flunet NHiberante cannot correctly handle the compatibleFilter argument.
So what I want is a way to convert the Func to Func or as suggested by John Skeet, an Expression<Func<IX, bool>> to an Expression<Func<X, bool>> which have the same body (y => y.Name = "John").
Edit 2:
Finally I made it happen! The correct way is not to use Func<X, bool>, but Expression<Func<X, bool>>.
Expression<Func<IX, bool>> filter = y => y.Name == "John Skeet";
Expression<Func<X, bool>> compatibleFilter = Expression.Lambda<Func<X, bool>>(
filter.Body,
filter.Parameters);
This produces the correct SQL query.IX, bool

A simple solution could be to use Func<X, bool> newFunc = x => filterFunc(x); where filterFunc is of type Func<IX, bool>. This would compile and one might expect it to run fine, but I assume it will not.
Why assume, when you can test? It should work absolutely fine. After all, you're passing an argument of type X for a parameter of type IX, which causes no type safety concerns.
You'll then need to convert from IEnumerable<X> to IEnumerable<IX>, which can be done with Cast for instance:
public IEnumerable<IX> Filter(Func<IX, bool> filterFunc)
{
Func<X, bool> newFilter = x => filterFunc(x);
return Filter(newFilter).Cast<IX>();
}

why do you use your concrete type isnt IX enough:
public class IXRepository : IRepository<IX>
{
public IEnumerable<X> Filter(Func<IX, bool> filterFunc)
{
...
}
}

As i understand it correctly, covariance is a language feature. So it does not depend directly on .net 4.

Related

Why can't I replace IEnumerable<T> by a generic type variable in extension method?

I am trying to make an extension method more generic to avoid redundancy (Here is an example of some real code, the code below is just to demonstrate the issue - I had the idea to make the method available for IQueryable<T> as well).
The following works fine:
public static class Extensions
{
public static IEnumerable<T> MySelect1<T, V>(this IEnumerable<T> query, Func<T, V> f)
{
// do something, then return IEnumerable<T>
var result=query.AsEnumerable<T>();
return result;
}
public static IQueryable<T> MySelect1<T, V>(this IQueryable<T> query, Func<T, V> f)
{
// do something, then return IQueryable<T>
var result = query.AsQueryable<T>();
return result;
}
}
I can use it in LinqPad like (when connected with the Northwind sample database):
var myQuery=(from x in Customers select x);
myQuery.AsEnumerable().MySelect1(d => d.CustomerID).Dump();
myQuery.AsQueryable().MySelect1(d => d.CustomerID).Dump();
Now I wanted to get rid of the duplicate implementation of MySelect1, so I refactored it as:
public static class Extensions
{
public static E MySelect2<E, T, V>(this E query, Func<T, V> f)
where E : System.Linq.IQueryable<T>, System.Collections.Generic.IEnumerable<T>
{
return (E)query.Select(f);
}
}
This compiles too, but I cannot use MySelect2 the same way as I did above, consider the following:
// CS0411 The type arguments for method 'Extensions.MySelect2<E, T, V>(E, Func<T, V>)'
// cannot be inferred from the usage. Try specifying the type arguments explicitly.
myQuery.AsEnumerable().MySelect2(d => d.CustomerID).Dump();
myQuery.AsQueryable().MySelect2(d => d.CustomerID).Dump();
Ok, doing what the error asks for works for this code line:
myQuery.AsQueryable()
.MySelect2<IQueryable<Customers>, Customers, String>(d => d.CustomerID).Dump();
but not for that one:
myQuery.AsEnumerable<Customers>()
.MySelect2<IEnumerable<Customers>, Customers, String>(d => d.CustomerID).Dump();
Here, I am getting
CS0311 The type 'System.Collections.Generic.IEnumerable<LINQPad.User.Customers>' cannot be used as type parameter 'E' in the generic type or method 'Extensions.MySelect2<E, T, V>(E, Func<T, V>)'. There is no implicit reference conversion from 'System.Collections.Generic.IEnumerable<LINQPad.User.Customers>' to 'System.Linq.IQueryable<LINQPad.User.Customers>'.
Why? And how can it be fixed? Please help.
Why?
For exactly the reason stated in the error message: you're trying to use IEnumerable<Customers> as the type argument for E, but E has this constraint:
where E : System.Linq.IQueryable<T>
And how can it be fixed?
It can't, assuming I understand what you're trying to achieve.
There's a fundamental problem with the "simplification" you're trying to achieve: you don't actually have full duplication in your original MySelect1 methods. The first calls AsEnumerable() and the second calls AsQueryable(). You're trying to replace those with a cast, and that's just not going to work.
There's a further problem, even with your original methods: you're accepting Func<T, V> f as a parameter for your queryable-based method, which means any time you call Select or similar and passing in f, you'll be calling Enumerable.Select instead of Queryable.Select. To really use IQueryable<> properly, you should accept Expression<Func<T, V>> f instead. At that point, you won't need to call AsQueryable anyway.
Your two methods "should" take radically different paths based on whether you're using LINQ to Objects or a different LINQ provider (e.g. LINQ to SQL), and that can't be hidden as a pure implementation detail without significant changes that would probably make it less useful than you want anyway.

Create a LinQ Expression with another Expression's Parameters

Vote my question to be closed
I have found a similar question and a really useful answer using
ExpressionVisitor class (Link:
How can I convert a lambda-expression between different (but compatible) models?).
Thank you all, I'm voting to my answer become closed as duplicate, please consider voting too.
Code
I'm developing a repository code that uses a Data Transfer Object, like the code below.
public class UsuarioRepositorio : IUsuarioRepository
{
private readonly MongoRepository<UsuarioDto> _Repository;
public UsuarioRepository(string connectionString)
{
_Repositorio = new MongoRepository<UsuarioDto>(connectionString, "");
}
}
public interface IUsuarioRepository
{
IEnumerable<T> Select(Expression<Func<Usuario, bool>> predicate);
}
UsuarioDto is the data transfer object for the Usuario class, both inheriting from the interface IUsuario.
The UsuarioRepository implements the IUsuarioRepository interface, and has a private member called _Repository, which belongs to the MongoRepository<UsuarioDto> type.
The _Repository member has a method called Select which accepts an argument of type Expression<Func<UsuarioDto, bool>>.
The IUsuarioRepository has a declared method called Select which accepts an argument of type Expression<Func<Usuario, bool>>.
Problem
The problem is that I need to implement the Select method in UsuarioRepository, using the IUsuarioRepository method signature and passing to _Repository a new expression of Expression<Func<UsuarioDto, bool>> type, with the same parameters of Expression<Func<Usuario, bool>> argument.
Basically I need a way to copy the expression parameters to a new expression of different type, knowing that the expressions has the same properties because they have the same interface inheritance. Something like this:
public IEnumerable<Usuario> Select(Expression<Func<Usuario, bool>> predicate)
{
Expression<Func<UsuarioDto, bool>> transferExpression = x => x != null;
transferExpression = transferExpression .Update(predicate.Body, predicate.Parameters);
return _Repository.Select(transferExpression ).ToList().Select(x => x.ToDomain());
}
Questions
The Update method of Expression type does work like the code above?
If it does not work, is there a way to copy expressions of different types, but with the same base/interface properties?
Thank you very much!
I have a blog post about combining 2 expressions of the same type here:
http://blog.waseem-sabjee.com/2013/07/23/linq-expression-how-to-append-to-an-expression-at-a-later-stage/
all you will need to do to achieve working with 2 types is alter the static methods in my extension class LambdaExtensions to work with T, T2 instead of T
a word of warning, if referencing a property of T2 that is not in T1, it may not be successful - you will need to handle this.
I've provided you with a starting point, and I will also be attempting this myself, I will update this answer later - but feel free to try it out yourself so long.

Type inference in repository methods

I have a RepositoryBase class where I define basic crud methods for my Entity Framework Context. I have these two overloads of the All() method:
public virtual IQueryable<T> All<TKey>(Expression<Func<T, bool>> predicate)
{
return All().Where(predicate);
}
public virtual PagedResult<T> All<TKey>(int startRowIndex, int maximumRows,
Expression<Func<T, TKey>> orderingKey, Expression<Func<T, bool>> predicate,
bool sortDescending = false)
{
var subset = All().Where(predicate);
IEnumerable<T> result = sortDescending
? subset.OrderByDescending(orderingKey).Skip(startRowIndex).Take(maximumRows)
: subset.OrderBy(orderingKey).Skip(startRowIndex).Take(maximumRows);
//More code ommited
}
The first method always needs me to explicitly specify the entity type, but the second doesn't. Why is this?
Example, this doesn't compile:
return All(s => s.LoanApplicationId == loanApplicationId)
And instead I must call it like this:
return All<LoanApplication>(s => s.LoanApplicationId == loanApplicationId)
But this DOES compile:
return All(0,10, s => s.Name, s => s.LoanApplicationId == loanApplicationId, false)
TKey is in the parameter list of the second (via Expression<Func<T, TKey>> orderingKey) and not the first. That supplies enough for the second to successfully infer the type when you use it with your supplied arguments (s => s.Name). You don't give yourself that luxury in the first version, so the compiler forces you to fill in the details by supplying the type parameter explicitly.
And from the looks of it, you don't need TKey in the first anyway, so possibly get rid of it (unless there is more code visible than that relatively simple implementation). And I don't think it means what your sample invocation thinks it means. TKey in the second is likely string (whatever the type of s.Name is), for example.

Error message "Operator '.' cannot be applied to operand of type 'lambda expression'" when converting a method to Extension Method?

I have a method which i want to convert to Extension Method
public static string GetMemberName<T>(Expression<Func<T>> item)
{
return ((MemberExpression)item.Body).Member.Name;
}
and calling it like
string str = myclass.GetMemberName(() => new Foo().Bar);
so it evaluates to str = "Bar"; // It gives the Member name and not its value
Now when i try to convert this to extension method by this
public static string GetMemberName<T>(this Expression<Func<T>> item)
{
return ((MemberExpression)item.Body).Member.Name;
}
and call it like
string str = (() => new Foo().Bar).GetMemberName();
Error says Operator '.' cannot be applied to operand of type 'lambda expression'
Where am I wrong?
There are really two things here, first, passing () => new Foo().Bar into the method that accepts Expression<Func<T>> treats the specified expression tree as a Expression<Func<T>>, but () => new Foo().Bar is not an Expression<Func<T>> on its own.
Second, in order to get your extension method to accept any lambda (such as you're supplying), you'd have to use the type that corresponds to any expression tree. But, as you may have already guessed based on the message ... to operand of type 'lambda expression' where you'd usually see the name of the type inside the quotes, that lambda expressions are treated specially by the language, making what you're trying to do, without casting first, impossible.
The way to invoke your extension method in extension method form would be (in the case that Bar is of type string)
((Expression<Func<string>>)(() => new Foo().Bar)).GetMemberName()`
which doesn't seem like it would be all that desirable.
Where am I wrong?
The compiler is telling you exactly what's wrong - you can't use . on a lambda expression.
The lambda expression doesn't have any particular type - it's just convertible to the expression tree.
A member-access expression (which is what you're trying to do) is only available in the forms
primary-expression . identifier type-argument-list(opt)
predefined-type . identifier type-argument-list(opt)
qualified-alias-member . identifier type-argument-list(opt)
... and a lambda expression isn't a primary expression.
Interestingly, this argument doesn't hold for an anonymous method expression, but for you still can't use a member access expression on that, either. Section 7.6.4 of the C# spec lists how a member access expression is bound, and the bulk of the options are either under "If E is a predefined-type or a primary-expression classified as a type" (which doesn't apply to anonymous methods) or "If E is a property access, variable, or value, the type of which is T" - but an anonymous method is an anonymous function, and as per section 7.15: "An anonymous function does not have a value or type in and of itself".
EDIT: You can still use extension methods on expression trees, you just can't use them directly on lambda expressions. So this will work:
Expression<Func<int>> expr = () => new Foo().Bar;
string name = expr.GetMemberName();
... but it's obviously not as useful. (Ditto with a cast as per mlorbetske's answer.)
To get typed expression, you will have to write it out. As others have said, there is no way compiler will automatically infer it from a lambda expression since a lambda expression can mean two things - either a delegate or an expression tree.
You can get the expression relatively simpler, by letting the compiler infer the type for you partially, like (from this answer):
public sealed class Lambda
{
public static Func<T> Func<T>(Func<T> func)
{
return func;
}
public static Expression<Func<T>> Expression<T>(Expression<Func<T>> expression)
{
return expression;
}
}
public sealed class Lambda<S>
{
public static Func<S, T> Func<T>(Func<S, T> func)
{
return func;
}
public static Expression<Func<S, T>> Expression<T>(Expression<Func<S, T>> expression)
{
return expression;
}
}
//etc, to cover more cases
Call it like:
var expr1 = Lambda.Expression(() => new Foo().Bar);
var expr2 = Lambda<string>.Expression(x => x.Length); //etc
Your options are:
Cast backward, to exact expression type and then call extension method on it
var name = ((Expression<Func<BarType>>)(() => new Foo().Bar)).GetMemberName();
looks ugly - cure worse than cause.
Get the expression first into a variable
Expression<Func<BarType>> expr = () => new Foo().Bar;
var name = expr.GetMemberName();
Slightly better, but still looks little off for a trivial thing.
Using the Lambda classes written above
var name = Lambda.Expression(() => new Foo().Bar).GetMemberName();
Even better. It's just a little less typing.
Your first pattern, which I think is the best you can get as far as readability goes
I dont think you can improve upon that considering C# rules related to lambda expressions. That said I think few improvements can be made.
First, extend the functionality to other lambda expression types. You would need more than Func<T> types to handle all cases. Decide what are the expression types you have to handle. For instance if you have a Func<S, T> type (as in your question - Bar on Foo), it looks better. Compare this
myclass.GetMemberName(() => new Foo().Bar);
with
myclass.GetMemberName<Foo>(x => x.Bar);
I would say these overloads would do:
//for static methods which return void
public static string GetMemberName(Expression<Action> expr);
//for static methods which return non-void and properties and fields
public static string GetMemberName<T>(Expression<Func<T>> expr);
//for instance methods which return void
public static string GetMemberName<T>(Expression<Action<T>> expr);
//for instance methods which return non-void and properties and fields
public static string GetMemberName<S, T>(Expression<Func<S, T>> expr);
Now these can be used not just in the cases mentioned in comments, surely there are overlapping scenarios. For instance, if you already have instance of Foo, then its easier to call the second overload (Func<T>) overload for name of property Bar, like myclass.GetMemberName(() => foo.Bar).
Secondly, implement a GetMemberName functionality common to all these overloads. An extension method on Expression<T> or LambdaExpression would do. I prefer the latter so that you get to call it even in non-strongly typed scenarios. I would write it like this, from this answer:
public static string GetMemberName(this LambdaExpression memberSelector)
{
Func<Expression, string> nameSelector = null;
nameSelector = e => //or move the entire thing to a separate recursive method
{
switch (e.NodeType)
{
case ExpressionType.Parameter:
return ((ParameterExpression)e).Name;
case ExpressionType.MemberAccess:
return ((MemberExpression)e).Member.Name;
case ExpressionType.Call:
return ((MethodCallExpression)e).Method.Name;
case ExpressionType.Convert:
case ExpressionType.ConvertChecked:
return nameSelector(((UnaryExpression)e).Operand);
case ExpressionType.Invoke:
return nameSelector(((InvocationExpression)e).Expression);
case ExpressionType.ArrayLength:
return "Length";
default:
throw new Exception("not a proper member selector");
}
};
return nameSelector(memberSelector.Body);
}
Lastly, GetMemberName is not a good name if you're to call it non-extension way. expression.GetMemberName() sounds more logical. Member.NameFrom<int>(x => x.ToString()) or MemberName.From<string>(x => x.Length) etc are more descriptive names for static calls.
So overall the class might look like:
public static class Member
{
public static string NameFrom(Expression<Action> expr)
{
return expr.GetMemberName();
}
public static string NameFrom<T>(Expression<Func<T>> expr)
{
return expr.GetMemberName();
}
public static string NameFrom<T>(Expression<Action<T>> expr)
{
return expr.GetMemberName();
}
public static string NameFrom<T>(Expression<Func<T, object>> expr)
{
return expr.GetMemberName();
}
}
And usage:
var name1 = Member.NameFrom(() => Console.WriteLine());
var name2 = Member.NameFrom(() => Environment.ExitCode);
var name3 = Member.NameFrom<Control>(x => x.Invoke(null));
var name4 = Member.NameFrom<string>(x => x.Length);
Most concise and clean.
For properties and fields, it can be transformed to an anonymous class and then using reflection the member name can be read, as shown here.
public static string GetMemberName<T>(T item) where T : class
{
if (item == null)
return null;
return typeof(T).GetProperties()[0].Name;
}
Call it like
var name = GetMemberName(new { new Foo().Bar });
It's faster, but has certain quirks, like not very refactor friendly, and doesnt help in case of methods as members. See the thread..
Of all I prefer 4.

C# Generic method type argument inference

Is there any way that I can generalise the type definitions here?
Ideally, I'd like to be able to change the type of 'testInput' and have test correctly infer the type at compile time.
public static void Run()
{
var testInput = 3;
var test = ((Func<int, int>) Identity).Compose<int,int,int>(n => n)(testInput);
Console.WriteLine(test);
}
public static Func<T, V> Compose<T, U, V>(this Func<U, V> f, Func<T, U> g)
{
return x => f(g(x));
}
public static T Identity<T> (this T value)
{
return value;
}
Update:
I can specify the type of the function passed into Compose but this still specifies the type in the line.
public static void Run()
{
var testInput = 3;
var identity = (Func<int, int>) Identity;
var test = identity.Compose((int n) => n)(testInput);
Console.WriteLine(test);
}
A little context; I'm working through Wes Dyer's The Marvel of Monads
Well seeing as I'm on a roll for spewing out text tonight I'll have my own stab at it. I should note that I am no expert on the C# compiler, I haven't read the specification (any of them... for anything), and although that article you linked was really interesting, I'd be lying if I said I was any sort of expert on that either (or even understood it all 100%).
Caveats aside, my take on your question is this:
Is there any way that I can generalise
the type definitions here?
I think the short answer is no. With the information provided, there is simply not enough information for the type inference part of C#'s compiler to infer enough information from the usage of the various variables.
As the other answers here demonstrate, it can be simplified. You can use #Lee's IdentityFunc to allow for type inference with var identity. However, even with this addition, it is still not possible with your sample code to infer all the type variables of Compose.
Imagine the following situation:
public static Func<T, V> Compose<T, U, V>(this Func<U, V> f, Func<T, U> g)
{
return x => f(g(x));
}
public static T Identity<T> (this T value)
{
return value;
}
public static Func<T, T> IdentityFunc<T>(this T value)
{
return (Func<T, T>)Identity;
}
and
public static void Run()
{
var a = 3; // a is int
var i = a.IdentityFunc(); // i is Func<int, int>;
var test = i.Compose(n => n)(a) // test is expected to be int
}
Initially this might appear as if test should easily be inferred to int. However, the return type of i.Compose can only be inferred after the fact, from its usage. The C# compiler obviously won't allow this.
public static void Run()
{
var a = 3; // a is int
var i = a.IdentityFunc(); // i is Func<int, int>;
var c = i.Compose(n => n) // c is Func<T, int> - T cannot be resolved without knowledge of n
var test = c(a); // ideally have type inference infer c (Func<T, int>) as Func<int, int>
}
In that example, upon usage of c with a the compiler would have to retrospectively infer the return type of the call to i.Compose<T, U, V>(n => n) to be Func<int, int>. This is obviously not possible in the C# compiler. Take away the call c(a) and the compiler would have no knowledge of the usage of c, which would remove any possibility of inferring T (not that it can anyway). It is possible a more advanced type inference system would be able to do this sort of inferring based on the usage of a generic return (possibly F# - another topic I'm no expert on).
As Wes Dyer doesn't provide specific usage of that particular example, it's unknown whether there is some other magic he uses to allow for the degree of type inference you're trying to achieve.
More qualified people like Eric Lippert would be able to provide you with a much greater level of detail (and technical accuracy / acuity). I read a great response he wrote on here to a question on type inference, but I can't find it. His blog has lots of great information. You could try contacting him if you're interested. Also, his answer to this question here discusses monads (and ultimately links back to Wes Dyer's article) buy you might be interested in reading it: Monad in plain English? (For the OOP programmer with no FP background)
You could write an extension method to return the Identity function for a type:
public static Func<T, T> IdentityFunc<T>(this T value)
{
return (Func<T, T>)Identity;
}
(or just return v => value;)
Your test then becomes
var testInput = 3;
var identity = testInput.IdentityFunc();
test = identity.Compose((int n) => n)(testInput);
The closest I can get is to explicitly type the parameter for the n => n lambda:
var test = ((Func<int, int>)Identity).Compose((int n) => n)(testInput);
I don't think you can achieve your ideal; C# type inference does not work like that.
You might enjoy F#.

Categories