how to get an attribute getter as a Func<object,object>? - c#

Intro
I am working on some code that relies heavily on reflection. Some parts that are at the core are used repeatedly. Optimizing this in even the slightest way will give me a lot(to various degrees) of performance benefits.
Context
The core consists of getting data out of an object. Currently I use reflection to get a PropertyInfo object, and then use the following code to construct a Func<object,object>:
public static Func<object, object> BuildUntypedGetter(PropertyInfo propertyInfo)
{
var targetType = propertyInfo.DeclaringType;
var methodInfo = propertyInfo.GetGetMethod();
var exTarget = System.Linq.Expressions.Expression.Parameter(typeof(object), "t");
var exBody0 = System.Linq.Expressions.Expression.Convert(exTarget, targetType);
var exBody = System.Linq.Expressions.Expression.Call(exBody0, methodInfo);
var exBody2 = System.Linq.Expressions.Expression.Convert(exBody, typeof(object));
var lambda = System.Linq.Expressions.Expression.Lambda<Func<object, object>>(exBody2, exTarget);
var action = lambda.Compile();
return action;
}
This resulting Func<object,object> is what I then cache and use. The actual typing and security for not calling it on other objects types but the original is something I do not have to worry about as this is taken care of.
In the above code, the lambda that is created looks like the following:
.Lambda #Lambda1<System.Func`2[System.Object,System.Object]>(System.Object $t) {
(System.Object).Call ((MyObjectType)$t).get_Id()
}
where Id is the attribute that this was generated on.
As you can see, this is merely a redirection. All it does is call the getter.
Question
Is there a way to just return the getter (get_Id) as a Func<object,object> without the extra cast and call? OR are there maybe other more efficient ways to call an object.attribute getter with an object type as instance type?

Is there a way to just return the getter (get_Id) as a
Func without the extra cast and call?
C# will not let you call getter without the cast (of course with the exception of dynamic type, but that's another story), because that would violate type safety, that C# guarantees.
But you can emit IL code, that does not contain such cast and calls getter directly. Of course, when you outsmart compiler like this, it is then your responsibility to call this method only on objects of correct type, otherwise your application is likely to crash.
Following code shows how to emit such IL code. My measurements indicates, that in Release mode, emitted delegate is approx. 3x faster than your compiled lambda (in Debug mode, it seems to be actually a bit slower).
public static Func<object, object> EmitUntypedGetter(PropertyInfo pi)
{
DynamicMethod method = new DynamicMethod(
"PropertyGetter",
typeof(Object),
new[] { typeof(Object) },
Assembly.GetExecutingAssembly().ManifestModule);
ILGenerator il = method.GetILGenerator(100);
// Load object onto the stack.
il.Emit(OpCodes.Ldarg_0);
// Call property getter
il.EmitCall(OpCodes.Callvirt, pi.GetGetMethod(), null);
// If property returns value-type, value must be boxed
if(pi.PropertyType.IsValueType)
il.Emit(OpCodes.Box, pi.PropertyType);
// Exit method
il.Emit(OpCodes.Ret);
return (Func<Object, Object>)method.CreateDelegate(typeof(Func<Object, Object>));
}
EDIT:
On my computer, performance of emitted code is consistently much faster that lambda version.
Tested on Windows 10 Home, CPU Intel Core2 Q9400, compiled with Visual Studio 2017 CE v. 15.4.0, Console App targeting .NET Framework 4.7, Release mode (Optimize code option in project properties enabled), executed outside of Visual Studio (with VS attached, some optimizations are disabled)
My results:
Compiled lambda (value type) : 40827 ms
Compiled lambda (reference type) : 37558 ms
Emit (value type) : 16963 ms
Emit (reference type) : 11903 ms
Program used for testing:
public struct MyClass
{
public int I => 42;
public string S => "foo";
}
public static void Main()
{
var valueTypeProperty = typeof(MyClass).GetProperty("I");
var referenceTypeProperty = typeof(MyClass).GetProperty("S");
var lambdaValueTypeGetterDelegate = BuildUntypedGetter(valueTypeProperty);
var lambdaReferenceTypeGetterDelegate = BuildUntypedGetter(referenceTypeProperty);
var emitValueTypeGetterDelegate = EmitUntypedGetter(valueTypeProperty);
var emitReferenceTypeGetterDelegate = EmitUntypedGetter(referenceTypeProperty);
//warm-up - ensures that delegates are properly jitted
lambdaValueTypeGetterDelegate(new MyClass());
lambdaReferenceTypeGetterDelegate(new MyClass());
emitValueTypeGetterDelegate(new MyClass());
emitReferenceTypeGetterDelegate(new MyClass());
TestDelegate("Compiled lambda (value type) ", lambdaValueTypeGetterDelegate);
TestDelegate("Compiled lambda (reference type) ", lambdaReferenceTypeGetterDelegate);
TestDelegate("Emit (value type) ", emitValueTypeGetterDelegate);
TestDelegate("Emit (reference type) ", emitReferenceTypeGetterDelegate);
Console.ReadLine();
}
private static void TestDelegate(string description, Func<object, object> getterDelegate)
{
const long LOOPS_COUNT = 1_000_000_000;
var obj = new MyClass();
Stopwatch sw = new Stopwatch();
sw.Start();
for (long i = 0; i < LOOPS_COUNT; i++)
{
getterDelegate(obj);
}
sw.Stop();
Console.WriteLine($"{description}: {sw.ElapsedMilliseconds} ms");
}

Is there a way to just return the getter (get_Id) as a Func without the extra cast and call?
Not in a way that satisfies your requirements. While it is generally possible to dynamically bind a delegate directly to a method (or property accessor), the delegate type must be signature-compatible with the method you are binding to. That's not the case for you.
Consider this example:
class MyClass {
string Id { get; set; }
}
Here, your accessor expressed in terms of Func<,> would be Func<MyClass, String>. You, however, want a Func<object, object>. You're changing both the argument type and the return type. That is only permissible within certain constraints.
The type Func<-T, +TReturn> is contravariant on its input type T and covariant on its output type TReturn. Thus, a Func<,> instance is convertible to another instantiation when the target type is more specific for T or less specific for TReturn. For example:
Func<object, *> is convertible to Func<string, *> because a function that takes in an object can always take in a string. The reverse is not true.
Func<*, string> is convertible to Func<*, object> because a function that returns a string always returns an object. Again, the reverse is not true.
In C#, these rules are strictly enforced. A generic parameter can be covariant when it only appears as an output; or contravariant when it only appears as an input. Furthermore, this variance is only applicable to reference types, meaning Func<*, int> is not assignable to Func<*, object>.
I'm afraid there's no way around it: any method you bind to a Func<object, object> must accept an object argument, which means you need an intermediate method that casts down to your source type. It also needs to explicitly box primitive return values. While you could eliminate some of the conversions by emitting the IL directly, as #Ňuf has shown, I don't think you'll see a meaningful impact.
However, depending on how you're using the values you pull out, there may be a better way. Instead of using generated code to pull values into the C# universe where you can operate on them, it may be feasible to do the opposite: push that logic down into generated code, which you could specialize according to the types you're working with. Or, alternatively, make that logic generic, and use the runtime code generation to dispatch to the correct generic instantiation.

Related

C#: Why does dynamic help determine type argument for use in generic methods?

I'm working with reflection to create some meta-tests to ensure equality between two instances of the same type.
As such, I'm using a lot of vars and generics.
One thing I've noticed is that with my generic functions, sometimes the Type argument is object (presumably when it can't determine the type) and other times it's the correct type.
Example:
Generic methods
public static RT[] CreateArrayWithNumItems<RT>(RT baseArgument, int numItems)
{
var a = new List<RT>();
for (int i = 0; i < numItems; i++)
a.Add((RT)DataObjectCreator.CreateUninitializedObject(typeof(RT)));
return a.Select(x => (RT)x).ToArray();
} //actual implementation more complex
private static T UnboxObject<T>(T boxedObject)
=> boxedObject;
public static object CreateUninitializedObject(Type typeObject)
=> typeObject == typeof(string) ? "" : FormatterServices.GetUninitializedObject(typeObject);
Use of methods:
var a = Model.GetType();
var unitializedObject = CreateUninitializedObject(a); //returns typed object
var objectArray = CreateArrayWithNumItems(unitializedObject, 1); //returns object array
var uob = UnboxObject(unitializedObject); //returns typed object
var uobObjectArray = CreateArrayWithNumItems(uob, 1); //returns object array
var typedArray = CreateArrayWithNumItems((dynamic) unitializedObject, 1); //returns typed object array
This seems strange to me (a.k.a I'm missing some knowledge), so I have a few questions about it.
Given the same variable, why does UnboxObject return a typed object and CreateArrayWithNumItems return an array of object?
Given the typed object uob why does CreateArrayWithNumItems return an array of object?
Lastly (and most importantly), why does casting to dynamic prior to calling CreateArrayWithNumItems allow the generic method to determine the type?
Without dynamic, the compiler performs all the type evaluations based on static analysis; assuming that CreateUninitializedObject returns object (presumably via FormatterServices), the call to CreateArrayWithNumItems infers the generic type parameters based on that static type, i.e.
var objectArray = CreateArrayWithNumItems(unitializedObject, 1);
becomes
var objectArray = CreateArrayWithNumItems<object>(unitializedObject, 1);
precisely because unitializedObject is object.
With dynamic, the runtime performs the work, but now it has knowledge of the actual object at runtime, so it knows that the type is (whatever Model is). The runtime then constructs something like:
dynamic objectArray = CreateArrayWithNumItems<TheActualType>((TheActualType)unitializedObject, 1);
(how it actually does it is much more complex; it could look for non-generic methods too, for example)
So yes, using dynamic can be a sneaky way to go from reflection (object/Type) code to strongly-typed generic code, but: it has a cost: dynamic involves more work at runtime - additional reflection, and additional runtime IL emit. You also need to be aware that typedArray is now also dynamic (unless you cast it to something else), so everything you do with typedArray becomes dynamic. Increasing costs.

Loading a ParameterInfo using IL Emit

I am currently using Calling a method of existing object using IL Emit as a guide, and I can already do whatever is asked in question. Now, I have an attribute added to a parameter and I want to load that particular parameter's attribute so that I can call a method inside that attribute.
I know it can be done by loading the MethodInfo and then getting the ParameterInfo and then getting attribute of that ParameterInfo in IL; I am simply trying to avoid writing that much IL.
Is there a way to load a parameter's attribute in IL just like it is mentioned in the linked post?
Edit:
I have a method with a signature like
Method([Attr] int Parameter)
and I want to load a method which is part of the Attr. I was just hoping I could load ParameterInfo (obtained using MethodInfo.GetParameters()) directly onto the stack. Turns out, LdToken doesn't really allow putting ParameterInfo. Only other way I can think of doing this is to load MethodInfo (LdToken supports that) and then use GetParameters() in IL to get an array of Parameters and then loop through them in IL one by one to get each one's Attribute (using .GetCustomAttribute(Type)) and then call the method on that attribute. Note that I don't have to get a field of an attribute, I need to call a method on that attribute.
K, third time lucky based on another interpretation of the question; here, we're assuming that we want to invoke methods on an attribute instance. We need to consider that attributes only kinda sorta exist at runtime - we can create synthetic instances of the attribute as represented by the metadata, but this isn't particularly cheap or fast, so we should ideally only do this once (the metadata isn't going to change, after all). This means we might want to store the instance as a field somewhere. This could be an instance field, or a static field - in many cases, a static field is fine. Consider:
using System;
using System.Reflection;
using System.Reflection.Emit;
public class SomethingAttribute : Attribute
{
public SomethingAttribute(string name)
=> Name = name;
public string Name { get; }
public void SomeMethod(int i)
{
Console.WriteLine($"SomeMethod: {Name}, {i}");
}
}
public static class P
{
public static void Foo([Something("Abc")] int x)
{
Console.WriteLine($"Foo: {x}");
}
public static void Main()
{
// get the attribute
var method = typeof(P).GetMethod(nameof(Foo));
var p = method.GetParameters()[0];
var attr = (SomethingAttribute)Attribute.GetCustomAttribute(p, typeof(SomethingAttribute));
// define an assembly, module and type to play with
AssemblyBuilder asm = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Evil"), AssemblyBuilderAccess.Run);
var module = asm.DefineDynamicModule("Evil");
var type = module.DefineType("SomeType", TypeAttributes.Public);
// define a field where we'll store our synthesized attribute instance; avoid initonly, unless you're
// going to write code in the .cctor to initialize it; leaving it writable allows us to assign it via
// reflection
var attrField = type.DefineField("s_attr", typeof(SomethingAttribute), FieldAttributes.Static | FieldAttributes.Private);
// declare the method we're working on
var bar = type.DefineMethod("Bar", MethodAttributes.Static | MethodAttributes.Public, typeof(void), new[] { typeof(int) });
var il = bar.GetILGenerator();
// use the static field instance as our target to invoke the attribute method
il.Emit(OpCodes.Ldsfld, attrField); // the attribute instance
il.Emit(OpCodes.Ldarg_0); // the integer
il.EmitCall(OpCodes.Callvirt, typeof(SomethingAttribute).GetMethod(nameof(SomethingAttribute.SomeMethod)), null);
// and also call foo
il.Emit(OpCodes.Ldarg_0); // the integer
il.EmitCall(OpCodes.Call, typeof(P).GetMethod(nameof(P.Foo)), null);
il.Emit(OpCodes.Ret);
// complete the type
var actualType = type.CreateType();
// assign the synthetic attribute instance on the concrete type
actualType.GetField(attrField.Name, BindingFlags.Static | BindingFlags.NonPublic).SetValue(null, attr);
// get a delegate to the method
var func = (Action<int>)Delegate.CreateDelegate(typeof(Action<int>), actualType.GetMethod(bar.Name));
// and test it
for (int i = 0; i < 5; i++)
func(i);
}
}
Output from the final loop (for (int i = 0; i < 5; i++) func(i);):
SomeMethod: Abc, 0
Foo: 0
SomeMethod: Abc, 1
Foo: 1
SomeMethod: Abc, 2
Foo: 2
SomeMethod: Abc, 3
Foo: 3
SomeMethod: Abc, 4
Foo: 4
As a side note; in many ways it is easier to do this with expression-trees, since expression-trees have Expression.Constant which can be the attribute instance, and which is treated like a field internally. But you mentioned TypeBuilder, so I went this way :)
I know it can be done by loading the MethodInfo and then getting the ParameterInfo and then getting attribute of that ParameterInfo in IL; I am simply trying to avoid writing that much IL.
Yeah, that's pretty much it, in IL; IL is powerful, but is not particularly terse or simple. Just like in the linked post, you'd end up loading the parameter (ldarg or ldarga, maybe some .s), then depending on whether the member is a field or a property, using either ldfld or callvirt on the property getter. About 3 lines, so not huge; perhaps something like:
static void EmitLoadPropertyOrField(ILGenerator il, Type type, string name)
{
// assumes that the target *reference* has already been loaded; only
// implements reference-type semantics currently
var member = type.GetMember(name, BindingFlags.Public | BindingFlags.Instance).Single();
switch (member)
{
case FieldInfo field:
il.Emit(OpCodes.Ldfld, field);
break;
case PropertyInfo prop:
il.EmitCall(OpCodes.Callvirt, prop.GetGetMethod(), null);
break;
default:
throw new InvalidOperationException();
}
}
If you're trying to save complexity (or are sick of InvalidProgramException), another viable approach is to use expression trees; then you have many more convenience features, but in particular things like:
var p = Expression.Parameter(typeof(Foo), "x");
var name = Expression.PropertyOrField(p, "Name");
// ...
var lambda = Expression.Lambda<YourDelegateType>(body, p);
var del = lambda.Compile();
Note that expression trees cannot be used in all scenarios; for example, they can't really be used with TypeBuilder; conversely, though, they can do things that IL-emit can't - for example, in AOT scenarios where IL-emit is prohibited, they can work as a runtime reflection evaluated tree, so it still works (but: slower). They add some additional processing (building and then parsing the tree), but: they are simpler than IL-emit, especially for debugging.
With the clarification that by attribute you really did mean a .NET attribute (not a field or property), this becomes simpler in many ways; consider:
class SomethingAttribute : Attribute
{
public SomethingAttribute(string name)
=> Name = name;
public string Name { get; }
}
static class P
{
public static void Foo([Something("Abc")] int x) {}
static void Main()
{
var method = typeof(P).GetMethod(nameof(Foo));
var p = method.GetParameters()[0];
var attr = (SomethingAttribute)Attribute.GetCustomAttribute(
p, typeof(SomethingAttribute));
string name = attr?.Name;
// you can now "ldstr {name}" etc
}
}
The important point here is that the attribute isn't going to change at runtime - it is pure metadata; so, we can load it once with reflection when we are processing the model, then just emit the processed data, i.e. the line
// you can now "ldstr {name}" etc
For future reference, I actually went ahead and loaded ParameterInfo using IL only. Marc's solution was good, but it quickly became infeasible after the number of parameter based attributes increased. We plan to use attributes to contain some state specific information, we would have to use a ton of reflection from outside the type to find and assign correct attribute to the field. Overall, it would have become quite hectic to deal with it.
To load ParameterInfo using IL
IL.Emit(OpCodes.Ldtoken, Method); // Method is MethodInfo as we can't use GetParameters with MethodBuilder
IL.Emit(OpCodes.Call, typeof(MethodBase).GetMethod(nameof(MethodBase.GetMethodFromHandle), new[] { typeof(RuntimeMethodHandle) }));
IL.Emit(OpCodes.Callvirt, typeof(MethodInfo).GetMethod(nameof(MethodInfo.GetParameters)));
var ILparameters = IL.DeclareLocal(typeof(ParameterInfo[]));
IL.Emit(OpCodes.Stloc, ILparameters);
that loads ParameterInfo onto stack and then stores it into a LocalBuilder called ILparameters. Note that it is an array. Items of this array can then be accessed like
IL.Emit(OpCodes.Ldloc, ILparameters);
IL.Emit(OpCodes.Ldc_I4, Number); // Replace with Ldc_I4_x if number < 8
IL.Emit(OpCodes.Ldelem_Ref);
I prefer to create two helper functions for the two code pieces. It works pretty well.

Any way to implement 'is'/'as' for dynamic or at least fake it?

I have a type ConfigValue that exposes a dynamic interface via an implementation of IDynamicMetaObjectProvider and custom DynamicMetaObject instance.
An instance of this type can be seen, of course, as it's native type - analogous to an XML Element - but it can also be seen as an instance of any other object type, according to the contents of the XML and what kind of object it builds (it's a proprietary IOC built by little old me).
So
<value>10</value>
Can be seen as a ConfigValue but also potentially a string, short, double etc. Conversion is achieved by implicit or explicit cast, as specified by the calling language. The XML gets more complicated because you can fire constructors, methods, property gets etc.
To achieve this, of course, I have overriden the BindConvert member of the DynamicMetaObject type - and if the conversion is unsupported by the ConfigValue object at runtime, then a runtime error occurs (which is fine).
I've just started writing a piece of code where it would be great if I could do a safe cast to the target type, but if that doesn't work fallback to some other logic - analogous to:
public DesiredType Foo(dynamic d)
{
DesiredType dt = d as dt;
if(dt != null)
return dt;
//TODO: Fallback logic to build dt from d
}
But, C# at least (and probably all dynamic-aware languages I'm sure) doesn't emit any dynamic binding for the 'as' or 'is' operations; presumably because DynamicMetaObject doesn't have a method for such a test. Thus the type test is just performed on the static type information which, in this case, always fails.
As a result I'm having to rely on the rather ugly:
public DesiredType Foo(dynamic d)
{
try
{
return (DesiredType)d;
}
catch(Exception)
{
//TODO: fallback logic
}
}
Any ideas how I can avoid the try/catch/gulp pattern here!? The best I can think of is something on top of DynamicMetaObject; but then that has to be queried for first, before then being queried again for the type test; which is just going to explode the code up even further!
I don't think it is possible.
Take for example, this code:
class Program
{
static void Main(string[] args)
{
dynamic d = new object();
var x = (Program)d;
Console.WriteLine(x);
var y = d as Program;
Console.WriteLine(y);
var z = d is Program;
Console.WriteLine(z);
}
}
If we decompile it using Reflector we see that the only reason that the cast is able to be intercepted by the dynamic type is that the C# compiler does a lot of extra work in order to support it:
class Program
{
private static void Main(string[] args)
{
object d = new object();
if (<Main>o__SiteContainer0.<>p__Site1 == null)
{
<Main>o__SiteContainer0.<>p__Site1 = CallSite<Func<CallSite, object, Program>>.Create(Binder.Convert(CSharpBinderFlags.ConvertExplicit, typeof(Program), typeof(Program)));
}
Console.WriteLine(<Main>o__SiteContainer0.<>p__Site1.Target(<Main>o__SiteContainer0.<>p__Site1, d));
Program y = d as Program;
Console.WriteLine(y);
bool z = d is Program;
Console.WriteLine(z);
}
}
In contrast, the as and is calls are simply compiled down to IL instructions, with no added magic from the C# compiler.
This fits in with the normal casting operators as well; using as rather than a cast will not perform any conversion casts, so will never change the type of the underlying object.
is and as are runtime tests that only work on inheritance, thus they don't need to dynamically bind because they are already dynamic. Even without the dynamic keyword you could never use is or as to test for implict or explicit conversions, and they never would work on value types like short and double either.
So your answer is that there is no need to fake it, they work exactly the same for dynamic types as static types. Your try catch is probably the best way to test the conversion, catching binding errors is what the DLR is already doing in the background for a lot of it's fallback cases. You can see for yourself in the debugger if you stop on first chance exceptions.
The best way to improve your try catch would be to specify the exact exception.
catch(RuntimeBinderException)
{
//TODO: fallback logic
}
In lieu of the fact that it's not supported, I've written this very basic static method to simplify the operation of testing the conversion.
public static class DynamicHelper
{
public static TResult As<TResult>(dynamic obj) where TResult : class
{
if (obj == null)
return null;
try
{
return (TResult)obj;
}
catch (Exception)
{
return null;
}
}
}
It's top-drawer code that ;)

Why can't an anonymous method be assigned to var?

I have the following code:
Func<string, bool> comparer = delegate(string value) {
return value != "0";
};
However, the following does not compile:
var comparer = delegate(string value) {
return value != "0";
};
Why can't the compiler figure out it is a Func<string, bool>? It takes one string parameter, and returns a boolean. Instead, it gives me the error:
Cannot assign anonymous method to an
implicitly-typed local variable.
I have one guess and that is if the var version compiled, it would lack consistency if I had the following:
var comparer = delegate(string arg1, string arg2, string arg3, string arg4, string arg5) {
return false;
};
The above wouldn't make sense since Func<> allows only up to 4 arguments (in .NET 3.5, which is what I am using). Perhaps someone could clarify the problem. Thanks.
UPDATE: This answer was written over ten years ago and should be considered to be of historical interest; in C# 10 the compiler will infer some delegate types.
Others have already pointed out that there are infinitely many possible delegate types that you could have meant; what is so special about Func that it deserves to be the default instead of Predicate or Action or any other possibility? And, for lambdas, why is it obvious that the intention is to choose the delegate form, rather than the expression tree form?
But we could say that Func is special, and that the inferred type of a lambda or anonymous method is Func of something. We'd still have all kinds of problems. What types would you like to be inferred for the following cases?
var x1 = (ref int y)=>123;
There is no Func<T> type that takes a ref anything.
var x2 = y=>123;
We don't know the type of the formal parameter, though we do know the return. (Or do we? Is the return int? long? short? byte?)
var x3 = (int y)=>null;
We don't know the return type, but it can't be void. The return type could be any reference type or any nullable value type.
var x4 = (int y)=>{ throw new Exception(); }
Again, we don't know the return type, and this time it can be void.
var x5 = (int y)=> q += y;
Is that intended to be a void-returning statement lambda or something that returns the value that was assigned to q? Both are legal; which should we choose?
Now, you might say, well, just don't support any of those features. Just support "normal" cases where the types can be worked out. That doesn't help. How does that make my life easier? If the feature works sometimes and fails sometimes then I still have to write the code to detect all of those failure situations and give a meaningful error message for each. We still have to specify all that behaviour, document it, write tests for it, and so on. This is a very expensive feature that saves the user maybe half a dozen keystrokes. We have better ways to add value to the language than spending a lot of time writing test cases for a feature that doesn't work half the time and doesn't provide hardly any benefit in cases where it does work.
The situation where it is actually useful is:
var xAnon = (int y)=>new { Y = y };
because there is no "speakable" type for that thing. But we have this problem all the time, and we just use method type inference to deduce the type:
Func<A, R> WorkItOut<A, R>(Func<A, R> f) { return f; }
...
var xAnon = WorkItOut((int y)=>new { Y = y });
and now method type inference works out what the func type is.
Only Eric Lippert knows for sure, but I think it's because the signature of the delegate type doesn't uniquely determine the type.
Consider your example:
var comparer = delegate(string value) { return value != "0"; };
Here are two possible inferences for what the var should be:
Predicate<string> comparer = delegate(string value) { return value != "0"; }; // okay
Func<string, bool> comparer = delegate(string value) { return value != "0"; }; // also okay
Which one should the compiler infer? There's no good reason to choose one or the other. And although a Predicate<T> is functionally equivalent to a Func<T, bool>, they are still different types at the level of the .NET type system. The compiler therefore cannot unambiguously resolve the delegate type, and must fail the type inference.
Eric Lippert has an old post about it where he says
And in fact the C# 2.0 specification
calls this out. Method group
expressions and anonymous method
expressions are typeless expressions
in C# 2.0, and lambda expressions join
them in C# 3.0. Therefore it is
illegal for them to appear "naked" on
the right hand side of an implicit
declaration.
Different delegates are considered different types. e.g., Action is different than MethodInvoker, and an instance of Action can't be assigned to a variable of type MethodInvoker.
So, given an anonymous delegate (or lambda) like () => {}, is it an Action or a MethodInvoker? The compiler can't tell.
Similarly, if I declare a delegate type taking a string argument and returning a bool, how would the compiler know you really wanted a Func<string, bool> instead of my delegate type? It can't infer the delegate type.
The following points are from the MSDN regarding Implicitly Typed Local Variables:
var can only be used when a local variable is declared and initialized in the same statement; the variable cannot be initialized to null, or to a method group or an anonymous function.
The var keyword instructs the compiler to infer the type of the variable from the expression on the right side of the initialization statement.
It is important to understand that the var keyword does not mean "variant" and does not indicate that the variable is loosely typed, or late-bound. It just means that the compiler determines and assigns the most appropriate type.
MSDN Reference: Implicitly Typed Local Variables
Considering the following regarding Anonymous Methods:
Anonymous methods enable you to omit the parameter list.
MSDN Reference: Anonymous Methods
I would suspect that since the anonymous method may actually have different method signatures, the compiler is unable to properly infer what the most appropriate type to assign would be.
My post doesn't answer the actual question, but it does answer the underlying question of :
"How do I avoid having to type out some fugly type like Func<string, string, int, CustomInputType, bool, ReturnType>?" [1]
Being the lazy/hacky programmer that I am, I experimented with using Func<dynamic, object> - which takes a single input parameter and returns an object.
For multiple arguments, you can use it like so:
dynamic myParams = new ExpandoObject();
myParams.arg0 = "whatever";
myParams.arg1 = 3;
Func<dynamic, object> y = (dynObj) =>
{
return dynObj.arg0.ToUpper() + (dynObj.arg1 * 45); //screw type casting, amirite?
};
Console.WriteLine(y(myParams));
Tip: You can use Action<dynamic> if you don't need to return an object.
Yeah I know it probably goes against your programming principles, but this makes sense to me and probably some Python coders.
I'm pretty novice at delegates... just wanted to share what I learned.
[1] This assumes that you aren't calling a method that requires a predefined Func as a parameter, in which case, you'll have to type that fugly string :/
Other answers were correct at the time they were written, but starting from C# 10.0 (from 2021), the compiler can infer a suitable delegate type (like some Func<...>, Action<...> or generated delegate type) in such cases.
See C# 10 Features - Lambda improvements.
var comparer = delegate(string value) {
return value != "0";
}; // OK in C# 10.0, picks 'Func<string, bool>' in this case
Of course the more usual syntax is to us =>, so:
var comparer = (string value) => {
return value != "0";
}; // OK in C# 10.0, picks 'Func<string, bool>' in this case
How is about that?
var item = new
{
toolisn = 100,
LangId = "ENG",
toolPath = (Func<int, string, string>) delegate(int toolisn, string LangId)
{
var path = "/Content/Tool_" + toolisn + "_" + LangId + "/story.html";
return File.Exists(Server.MapPath(path)) ? "<a style=\"vertical-align:super\" href=\"" + path + "\" target=\"_blank\">execute example</a> " : "";
}
};
string result = item.toolPath(item.toolisn, item.LangId);

Can I capture a local variable into a LINQ Expression as a constant rather than a closure reference?

I'd like to say
int x = magic(), y = moremagic();
return i => i + (x/y);
and have the x be captured as a constant instead of a variable reference. The idea is that x will never change and so when the expression is later compiled, the compiler to can do constant folding and produce more efficient code -- i.e. calculating x/y once instead of on every call, via pointer dereferences into a closure record.
There is no way to mark x as readonly within a method, and the compiler is not clever enough to detect that it doesn't change after the creation of the expression.
I'd hate to have to build the expression by hand. Any brilliant ideas?
UPDATE: I ended up using the marvelous LinqKit to build a partial evaluator that will do the substitutions I want. The transform is only safe if you know that relevant references will not change, but it worked for my purposes. It is possible to restrict the partial evaluation only to direct members of your closure, which you control, by adding an extra check or two in there, which is fairly obvious on inspection of the sample code provided in the LinqKit.
/// <summary>Walks your expression and eagerly evaluates property/field members and substitutes them with constants.
/// You must be sure this is semantically correct, by ensuring those fields (e.g. references to captured variables in your closure)
/// will never change, but it allows the expression to be compiled more efficiently by turning constant numbers into true constants,
/// which the compiler can fold.</summary>
public class PartiallyEvaluateMemberExpressionsVisitor : ExpressionVisitor
{
protected override Expression VisitMemberAccess(MemberExpression m)
{
Expression exp = this.Visit(m.Expression);
if (exp == null || exp is ConstantExpression) // null=static member
{
object #object = exp == null ? null : ((ConstantExpression)exp).Value;
object value = null; Type type = null;
if (m.Member is FieldInfo)
{
FieldInfo fi = (FieldInfo)m.Member;
value = fi.GetValue(#object);
type = fi.FieldType;
}
else if (m.Member is PropertyInfo)
{
PropertyInfo pi = (PropertyInfo)m.Member;
if (pi.GetIndexParameters().Length != 0)
throw new ArgumentException("cannot eliminate closure references to indexed properties");
value = pi.GetValue(#object, null);
type = pi.PropertyType;
}
return Expression.Constant(value, type);
}
else // otherwise just pass it through
{
return Expression.MakeMemberAccess(exp, m.Member);
}
}
}
No there is no way to do this in C#. The compiler does not support capturing variables by value / const. Nor can you convert a non-const value into a const value at runtime in this manner.
Additionally the C# compiler only does constant folding during the initial compilation for known constant values. If it was possible to freeze a value at runtime into a constant it wouldn't participate in compiler constant folding because it happens at runtime.
The compiler doesn't do this type of "value caching". Constant folding is done at compile time for constants only, not for readonly fields and certainly not for local variables which do not have a known value at compile time.
You have to make this yourself, but it has to stay a closure reference (since the value is in fact not determinable at compile time, which is why it is likely to be put in the closure when the expression is built):
int x = magic(), y = moremagic();
int xy = x/y;
return i => i + xy;
x can't be a constant, because you're doing runtime magic to determine what it is. However, if you know that x and y don't change, try:
int x = magic(), y = moremagic();
int xOverY = x/y;
return i => i + xOverY;
I should also mention that even though the compiled IL code for i => i + (x/y) will show the division, the JIT compiler is almost certainly going to optimize this away.
One technique I used in vb2005 was to use a generic delegate factory to effect by-value closures. I only implemented it for subs rather than functions, but it could be done for functions as well. If extended in that way:
FunctionOf.NewInv()
would be a static function which would accept as parameters a function (described later), a T3, and a T4. The passed-in function should accept parameters of types T2, T3, and T4, and return a T1. The function returned by NewInv would accept one parameter of type T2 and call the passed-in function with that parameter and the ones given to NewInv.
The invocation would look something like:
return FunctionOf.NewInv((i,x,y) => i+x/y, x, y)
If you(like me) are creating some expression builder for SQL queries you may consirer the following: first create a class variable, make it a constant and then access it like this:
var constant= Expression.Constant(values);
var start = Expression.MakeMemberAccess(constant, values.GetMemberInfo(f => f.Start));
var end = Expression.MakeMemberAccess(constant, values.GetMemberInfo(f => f.End));
var more = Expression.GreaterThanOrEqual(memberBody, start);
var less = Expression.LessThanOrEqual(memberBody, end);

Categories

Resources