Generic extension method : Type argument cannot be inferred from the usage - c#

I'm trying to create a generic extension method, that works on typed data tables :
public static class Extensions
{
public static TableType DoSomething<TableType, RowType>(this TableType table, param Expression<Func<RowType, bool>>[] predicates)
where TableType : TypedTableBase<RowType>
where RowType : DataRow
{
// do something to each row of the table where the row matches the predicates
return table;
}
[STAThread]
public static void main()
{
MyTypedDataSet.MyTypedDataTable table = getDefaultTable();
}
public static MyTypedDataSet.MyTypedDataTable getDefaultTable()
{
// this line compiles fine and does what I want:
return new MyTypedDataSet.MyTypedDataTable().DoSomething<MyTypedDataSet.MyTypedDataTable, MyTypedDataSet.MyTypedRow>(row => row.Field1 == "foo");
// this line doesn't compile :
return new MyTypedDataSet.MyTypedDataTable().DoSomething(row => row.Field1 == "foo");
// Error : The type arguments .. cannot be inferred from the usage
}
}
The first line works fine, but it's really ugly...
The second line doesn't compile because the compiler cannot infer the type of RowType.
This is a method that will be used as part of a DataLayer by many different programmers, so I would rather not need them to specify the TypeParameter.
Shouldn't the compiler know that RowType is the same type as the one that was used by TypedTableBase ?
For different reasons that may not be obvious in this code sample, I really need to return the datatable in its original form. And the reason I need RowType is so the 'Expression<Func<T, bool>>' will be typed and seen by InteliSence.
Thanks

Method type inference does not make inferences from arguments to constraints. It makes inferences from arguments to formal parameters and then checks whether the inferences made from the arguments to the formals satisfy the constraints.
In your case there is not enough data from the arguments to deduce what the type parameters are without first looking at the constraints, which we're not going to do until we check the inferences against the constraints. Sorry about that, but that's how the type inference algorithm is specified.
I've been asked questions about this many times and the consensus seems to be that I am morally wrong for maintaining the position that inference should infer from arguments to formal parameters alone. For about a dozen people telling me I'm wrongheaded in this regard, see the comments to my analysis of this closely related issue:
http://blogs.msdn.com/b/ericlippert/archive/2009/12/10/constraints-are-not-part-of-the-signature.aspx
I maintain my position.

Eric's answer is great for explaining why the types cannot be inferred. Here are a couple of suggestions to hopefully cut down on the verbosity of the code that you will have to write.
If you can explicitly define the type of your lambda expression, then it can infer the types.
One example of how to do that is below. I've created a criteria parameter that is explicitly of type Expression<Func<MyTypedDataSet.MyTypedRow, bool>>. In this example, this doesn't save you much typing, but perhaps in practice you can make use of this.
MyTypedDataSet.MyTypedDataTable table = new MyTypedDataSet.MyTypedDataTable();
Expression<Func<MyTypedDataSet.MyTypedRow, bool>> criteria = row => row.Field1 == "foo";
return table.DoSomething(criteria);
EDIT: altered my example to use another extension method rather than deriving a custom TypedTableBase<T> class from System.Data.TypedTableBase<T>.
Below is another example that can do a better job of inferring the type parameters. You define another extension method (mine is called RowPredicate) that only has one type parameter to infer. The first parameter is of type TypedTableBase<RowType>, so the compiler should have no problem inferring the type from that:
public static Expression<Func<RowType, bool>> RowPredicate<RowType>(this TypedTableBase<RowType> table, Expression<Func<RowType, bool>> predicate)
where RowType : DataRow
{
return predicate;
}
This allows you to compile the following code:
MyTypedDataSet.MyTypedDataTable table = new MyTypedDataSet.MyTypedDataTable();
return table.DoSomething(table.RowPredicate(row => row.Field1 == "foo"));
Primarily the table parameter simply servers to inform the compiler of the type to use for RowType. Is this a good idea? I'm not so sure, but it does allow the compiler to infer all of the generic types.

Even if that wasn't ideal, I gave up trying to return anything at all which allows me to do something like the following:
public static void DoSomething<RowType>(this TypedTableBase<RowType> table, param Expression<Func<RowType, bool>>[] predicates)
where RowType : DataRow
{
// do something to each row of the table where the row matches the predicates
// do not return the table... too bad for chaining commands
}
And then use it like so:
MyTypedDataSet.MyTypedDataTable table = new MyTypedDataSet.MyTypedDataTable();
table.DoSomething(row => row.Field1 == "foo"));
and the compiler infers the type correctly.
Thank you both for your answers.

Related

Explicit cast in c# generic

The non-generic version of CastRangeAndAdd works fine. If I skip the (object)
var castedList = list.Select(e => (NewType)e).ToList();
then there is a compile error. If I use the (object) then there is an exception "type TypeHintExcel can not be converted to TypeHint" though the cast operator is there. Any idea? (TypeHint and TypeHintExcel are not related so as I understand the "as keyword" can not be used.)
public static explicit operator TypeHint(TypeHintExcel p)
{
var result = new TypeHint()
{
Id = p.Id,
Hint = p.Hint,
ExternalType = p.ExternalType,
AlienType = p.AlienType,
Weight = p.Weight
};
return result;
}
public static class DbSetExtensions
{
public static void CastRangeAndAdd<OldType, NewType>
(this System.Data.Entity.DbSet<NewType> dbCollection,
List<OldType> list)
where NewType : class
{
var castedList = list.Select(e => (NewType)(object)e).ToList();
dbCollection.AddRange(castedList);
}
}
You can't write a generic method to do this. The explicit conversion operation needs to be bound at compile time, but when that method is compiled it has no idea what the source and destination types are, so it can't possibly be bound to your custom conversion operator.
c# is not as flexible as c++
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/differences-between-cpp-templates-and-csharp-generics
C++ allows code that might not be valid for all type parameters in the template, which is then checked for the specific type used as the type parameter. C# requires code in a class to be written in such a way that it will work with any type that satisfies the constraints. For example, in C++ it is possible to write a function that uses the arithmetic operators + and - on objects of the type parameter, which will produce an error at the time of instantiation of the template with a type that does not support these operators. C# disallows this; the only language constructs allowed are those that can be deduced from the constraints.

Assign a function delegate that returns an anonymous type to a variable

The code below is valid:
IEnumerable<SomeThing> things = ...;
// map type SomeThing to a new anonymous type, resulting in a strongly typed
// sequence based on an anon type
var newList = things.Select(item =>
{
return new
{
ID = item.ID,
DateUpdatedOrCreated = ((DateTime)(item.DateUpdated ??
item.DateCreated)).ToShortDateString(),
Total = item.Part1 + item.Part2
};
});
newList now appears in Visual Studio as IEnumerable<'a> and is strongly typed with the anonymous type created in the function. That is so cool.
What I can't seem to do is figure out a way to assign just the lambda expression (and not the enumeration) to an implicitly typed variable. Even though the compiler has no problem with the anonymous type in the context above, if I try (say)
var func = (SomeThing item)=> {
return new { ... };
};
I get the error "Cannot assign lambda expression to implicitly-typed local variable". This seems a strange compiler limitation; unless I am missing something, the types are just as non-ambiguous in the 2nd example as they are in the first first: both type parameters are well defined.
Is there any way to do this? Since it's an anonymous type, of course, I don't have any way to use a type to assign it explicitly, so it seems I'd be stuck with making a class for the output type if not.
Update
Shortly after going about my merry way with Jon Skeet's answer, I found a similar dilemma instantiating classes. In case it's not obvious, the same trick can be used to create strongly typed classes using inferred anonymous types.
class Processor<T,U>
{
public Processor(Func<T,U> func) {
}
}
// func is a delegate with anon return type created using method in answer below
var instance = new Processor(func); // does not compile! Requires type arguments!
cannot be created directly, but can be created in much the same way as the trick below:
public static Processor<T,U> Create<T,U>(Func<T,U> func) {
return new Processor<T,U>(func);
}
var instance = Processor.Create(func); // all good
You can do it via type inference:
var func = BuildFunc((SomeThing item) => {
return new { ... };
});
...
static Func<TSource, TResult> BuildFunc<TSource, TResult>(
Func<TSource, TResult> function) {
return function;
}
Note that BuildFunc doesn't really do anything - it just provides the method call needed to get the compiler to do type inference for the generic type arguments for Func<,> - it adds the information that you're interested in Func<,>, basically - that's information which can't be specified as part of a variable declaration, without also specifying the type arguments.

Executing DynamicExpression with unknown types

If anyone is very familar with the Linq.Dynamic namespace I could use some help -- couldn't find any indepth resources on the internet.
Basically I'm using DynamicExpression.ParseLambda to create an expression where the type is not known at compile time,
public Expression GetExpression(Type t, List<QueryFilter> filters)
{
// pseudo code
// extracts a string representation of the query as 'expressionString'
return DynamicExpression.ParseLambda(t, typeof(Boolean), expressionString, values);
}
Where a QueryFilter is:
public class QueryFilter
{
string propertyName;
ExpressionType operationType;
object value;
}
Which represents a simple binary function like "Age > 15" or something.
This is how the 'GetExpression' function works, it takes 2 types -- one that is the input type and one that is the output type, and ultimately generates what would normally be created with a Func delegate. It also takes a string that represents the query and a params object[] of values, which are 'expressionString' and 'values' above, respectively.
However I am having trouble executing the dynamic expression in LINQ-to-SQL, using a DataContext generated from SqlMetal (.dbmc file).
DatabaseContext db = new DatabaseContext(connectionString);
var filter = DynamicExpressionBuilder.
GetExpression(typeof(SysEventLogT), sysEventFilters)
var query = db.SysEventLogT.Where(filter);
Produces the following error,
System.Data.Linq.Table<DBReporting.Linq.Data.SysEventLogT>
does not contain a definition for 'Where' and the best extension method overload
System.Linq.Dynamic.DynamicQueryable.Where<T>(System.Linq.IQueryable<T>, string, params object[])
has some invalid arguments.
I know that my DataContext instance actually treats the sql tables as properties...do I need to reflect with GetProperty() somehow for this to work? Or perhaps I need to create another .Where extension?
Your GetExpression is returning an Expression type - the DynamicQueryable.Where method, when used as an extension method, expects a string as the first parameter.
You need your call to Where to look like this:
var query = db.SysEventLogT.Where("Age > #0", 15);
Also, you could try the following, just to be explicit:
var query = db.SysEventLogT.AsQueryable().Where("Age > #0", 15);
Note that if easier, you can build a sting containing the full filter and not use the params object[] parameter at all:
var query = db.SysEventLogT.AsQueryable().Where("Age > 15");

How to return Anonymous Type while using Linq [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
LINQ to SQL: Return anonymous type?
Do any one know how to return an anonymous type. I am using Linq where i need to return the following code
private <What's the return type to be provided here> SampleLinq(Int32 Num)
{
var query = (from dept in obj.DeptTable where dept.Id == Num select new { dept.DeptName, dept.DeptId });
return (query)
}
Sorry to say but you cannot return anonymous type out side the scope of method.
This is the alternate way to get anonmous type
// Method that returns anonymous type as object
object ReturnAnonymous()
{
return new { City="Prague", Name="Tomas" };
}
// Application entry-point
void Main()
{
// Get instance of anonymous type with 'City' and 'Name' properties
object o = ReturnAnonymous();
// This call to 'Cast' method converts first parameter (object) to the
// same type as the type of second parameter - which is in this case
// anonymous type with 'City' and 'Name' properties
var typed = Cast(o, new { City="", Name="" });
Console.WriteLine("Name={0}, City={1}", typed.Name, typed.City);
}
// Cast method - thanks to type inference when calling methods it
// is possible to cast object to type without knowing the type name
T Cast<T>(object obj, T type)
{
return (T)obj;
}
you can use it only for types in one assembly (two anonymous types from two different assemblies will be internally compiled to two different types that can't be converted using this trick).
Return Dynamic type:
public static dynamic getCustomer()
{
.....
var x = from c in customers
select new {Fname = c.FirstName};
return x;
}
static void Main(string[] args)
{
dynamic x = getCustomer();
Console.WriteLine(Enumerable.First(x).Fname);
Console.ReadKey();
}
you can't do that. that is why it is called anonymous. It doesn't have a name. But you always can cast it to object
Well, you can't actually do that, but here's a hack on this.
private object SampleLinq(Int32 Num)
{
return (from dept in obj.DeptTable where dept.Id == Num select new { dept.DeptName, dept.DeptId });
}
You can't return an Anonymous Type from a method.
You can create a simple Class to wrap the Anonymous Type, but you still need a Class (or cast to object).
Keep in mind, though, that if you cast to object there's no way to cast back. You'll need reflection to read any data.
The answers you see from the hack is a lot of work just to get an anonymous type through a method boundary. You shouldn't be doing this. If you need to pass something back from a method, you should be passing concrete types.
It depends what you looking to do with the return vale.
If your going to bind it in the UI
you can just rerun
IEnumerable or IQueryable.
If your going to use reflection on the return value just return type object
If your using c# 4.0 you can return a
dynamic type
If your using EF or Linq to SQL to further join a query comprised of your anonymous type you
can make a concrete class instead and
use the concrete placeholder
technique. For more details on this
technique I can give some assistance.
As others have mentioned though, you should really question whether returning an anonymous type form a method is the best way to solve the problem at hand. In general there is usually a better more pattern based approach that may require a bit more coding up front but may resulting in a more elegant design. This being said, I do believe there are legitimate cases such as with data binding where returning anonymous type instances can be perfectly acceptable.
UPDATE:
Just an interested tidbit I wanted to share in case those reading are not aware. Anonymous types are unique per their property names and types so lets say you have method A and method B in in both you create an anonymous type that has a single string typed property called Name by doing something like be code below.
public object A()
{
return new { Name = "Cid" }
}
public object B()
{
return new { Name = "Galuf" }
}
public void Test()
{
System.Diagnostics.Trace.Assert(A().GetType() == B().GetType());
}
Now even though this type is defined in two separate places the compiler only creates only creates a single shared type because they both have the same set of properties as defined by the property types and property names. In this respect the properties can be thought of as sort of a signature for the anonymous type. Using this knowledge there are different techniques that can be used for introspection into anonymous type instances that have been cast to object or deferred using the dynamic keyword. There are also nifty ways to work with anonymous types by using generic methods just as Linq does with methods in the static Enumerable and Queryable classes. This way you can do things like create a new instance of any given anonymous type and without using reflection. The trick is though that you have to use an instance of the anonymous type to pass to methods in order to have the type be inferred by the generic method. If anybody is interested in these topics further as they apply to the original posters question, leave a comment and I can try to clarify some of these techniques.

C# Get Delegate (Func) implementation from concrete class via reflection?

Sorry for the poor explaination of the problem
Totally rewriting question
I have the following method:
public TReturn FindCached<TSearch, TReturn>(Func<TSearch, TReturn> searchMethod)
where TSearch : ISearchSpecification
where TReturn : class
{
SearchSpecification spec = new GetConcreteSearchSpecification<TSearch>();
//insert magic here to get an attribute from the method on
//the spec class that searchMethod invokes on the line below
return searchMethod(spec);
}
So I have a delegate (searchMethod) and an object (spec) that I want to invoke the delegate on. I want to inspect the object (spec) to find a custom attribute on the method that searchMethod will call when invoked.
Hope this is clearer.
Thanks
Assuming you meant searchMethod to be a variable of type Func<TSearch, TReturn> and mySearchSpec as some implementation of ISearchSpecification<TSearch>, then you are basically asking how to get attributes on a class.
For this, use something like:
object[] attrs = typeof(mySearchSpec).GetCustomAttributes(false);
Assuming that the mySearchSpec type is public, otherwise you may need a different overload for GetCustomAttributes
Addendum:
Based on your revised question, to get the attributes on a method on the actual type of spec used:
Type t = spec.GetType();
MethodInfo m = t.GetMethod("nameOfMethodToBeCalledHere");
object[] attrs = m.GetCustomAttributes(false);
Again, note that you may need overloads for GetMethod or GetCustomAttributes depending on the implementation of the actual class.
Note:
It does seem however like you might be asking for the method called in return searchMethod(spec);, but that is searchMethod and not some method on spec at all.
If you want attributes on searchMethod (nothing to do with spec):
MethodInfo m = searchMethod.Method;
object[] attrs = m.GetCustomAttributes(false);
I think that now covers all permutations of meaning...
This is quite a confusing question, let's see if I have it right:
You have a lambda function (which you describe as a delegate) called searchMethod.
You have a factory-pattern generated object called spec
So you have a method somewhere like this:
[MyCustomAttribute]
public RetClass MyMethod( SearchSpecification input ) {
return input.GetRetClass();
}
And you call this method with:
var result = FindCached( MyMethod );
And in FindCached you want to find MyCustomAttribute - in that case #jerryjvl's answer is right.
Your problem is that you could also do:
var result = FindCached( x => x.GetRetClass() );
I'm not sure from your description whether it's an attribute on the x.GetRetClass() that you actually want. In this case you need to take the lambda apart using expressions, but I wouldn't recommend it - a more complex lambda declaration will result in an anonymous delegate, which is a black-box when you try to parse it at run time.
Instead, as you're using reflection anyway, it might be easier to pass the name of the method that you want instead of the delegate reference:
var result = FindCached( "GetRetClass" );
I ran into a similar situation, jerryjvl's answer explained exactly what I wanted.
I wanted to create a generic profiling method, where I could time how long some method took to run, and retrieve the name of the method using reflection for logging purposes.
The MethodInfo was the key.
Where I have a method like:
public static bool TimeMethod(Func<bool> someMethod)
And then later I want to dynamically get it's name or some attributes off it.
MethodInfo m = someMethod.Method;
object[] attrs = m.GetCustomAttributes(typeof(MonitoringDescriptionAttribute), true);
string name = m.Name;
Cheers

Categories

Resources