What is the difference between Expression.Variable() and Expression.Parameter()? - c#

Both seem to return the same type, and have the same signature.
So what is the difference between them, and when should we use each?

Expression.Variable is used to declare a local variable within a block. Expression.Parameter is used to declare a parameter for an incoming value.
Now currently C# doesn't allow statement-bodied lambda expressions, but if it did, imagine:
// Not currently valid, admittedly...
Expression<Func<int, int>> foo = x =>
{
int y = DateTime.Now.Hour;
return x + y;
};
If this were valid, the C# compiler would generate code using Expression.Parameter for x, and Expression.Variable for y.
At least, that's my understanding. It's a real shame that the documentation for the two methods is basically the same :(

Effectively, there is no difference, apart from the fact that Variable() does not allow ref types. To see that, you can look at the reference source:
public static ParameterExpression Parameter(Type type, string name) {
ContractUtils.RequiresNotNull(type, "type");
if (type == typeof(void)) {
throw Error.ArgumentCannotBeOfTypeVoid();
}
bool byref = type.IsByRef;
if (byref) {
type = type.GetElementType();
}
return ParameterExpression.Make(type, name, byref);
}
public static ParameterExpression Variable(Type type, string name) {
ContractUtils.RequiresNotNull(type, "type");
if (type == typeof(void)) throw Error.ArgumentCannotBeOfTypeVoid();
if (type.IsByRef) throw Error.TypeMustNotBeByRef();
return ParameterExpression.Make(type, name, false);
}
As you can see, both methods call ParameterExpression.Make(), so the returned object will behave the same.

Related

Clever way to add two objects

I'm trying to make some method like below.
It just add two given objects and return.
object add(object a, object b);
I already tried it with dynamic keyword. Unfortunately this one does not work on iOS. (the platform does not allow runtime code generations)
dynamic add(dynamic a, dynamic b) => a + b;
So, here's my second try and I realized that it's gonna be hell with this way.
private static HybInstance Add(HybInstance a, HybInstance b)
{
if (a.Is<Int32>()) return AddInt32(a, b);
/* and so on... */
}
private static HybInstance AddInt32(HybInstance a, HybInstance b)
{
Int32 ia = a.As<Int32>();
if (b.Is<Int16>()) return HybInstance.Int(ia + b.As<Int32>());
if (b.Is<Int32>()) return HybInstance.Int(ia + b.As<Int32>());
if (b.Is<Int64>()) return HybInstance.Int64(ia + b.As<Int64>());
if (b.Is<float>()) return HybInstance.Float(ia + b.As<float>());
throw new SemanticViolationException($"");
}
// the method should support custom operators too
private static MethodInfo GetAddMethod(HybInstance left) {
return left.GetMethods("op_Addition").FirstOrDefault();
}
Is there any smarter way to add two objects?
addition:
Here are some examples what I want to do.
Just add any kind of objects or throw exception if not possible.
add(1, 1); // 2
add(1, "b"); // exception
add("a", "b"); // "ab"
// and this one also should be work
add(some_class_with_operator_overloading, 10);
Closest you could get using standard .NET types is probably IConvertible:
static IConvertible Add (IConvertible a, IConvertible b)
{
if (a is string) return a.ToString() + b;
if (b is string) return a + b.ToString();
// other special cases here
return a.ToDouble(CultureInfo.CurrentCulture) + b.ToDouble(CultureInfo.CurrentCulture);
}
static void Main(string[] args)
{
IConvertible a = 1;
IConvertible b = 2;
IConvertible s = "string";
Console.WriteLine(Add(a, b));
Console.WriteLine(Add(s, s));
Console.WriteLine(Add(a, s));
}
Produces
3
stringstring
1string
It's impossible to add two objects, because there's nothing about objects that can be added.
It's like you would like add "something" to "something" and expected someone to answer your question with precise answer - it's impossible.
object don't have any fields or properties, so how you'd like to add them??
Unless you have in mind some kind of general rule of adding objects based on their real type, then it would become possible: you would have to check the type of input parameters and then in (rather) huge switch statement return appropriate result (eg. concatenation for strings, simple addition for integers...).
Did you try with generics, 2 things though:
You are wrapping different objects in same wrapper, seems like a design issue, but will leave it since I do not know more.
Most of the int can be directly changed to Int64 and then there will not be that many special cases
I would have a generic function, and would pass it the Add/Combine function which can be defined for different types. Seems to be a cleaner approach.
public T Add<T1, T2, T>(T1 firstObject, T2 secondObject, Func<T1,T2,T>Combine)
{
var result = Combine(firstObject, secondObject);
return result;
}
Update
Seems like this will not work either
Limitations of Xamarin.iOS
No Dynamic Code Generation
Since the iOS kernel prevents an application from generating code dynamically, Xamarin.iOS does not support any form of dynamic code generation. These include:
The System.Reflection.Emit is not available.
No support for System.Runtime.Remoting.
No support for creating types dynamically (no Type.GetType ("MyType`1")), although looking up existing types (Type.GetType ("System.String") for example, works just fine).
Reverse callbacks must be registered with the runtime at compile ti
However
Why does LambdaExpression.Compile() work on iOS (Xamarin)?
On platforms that support code generation, Reflection.Emit-based
LambdaCompiler
is used.
If that's not available, the expression is interpreted using the
interpreter
For example, there are classes that interpret Constant and Add.
Original
I am not sure how much mileage you could get out of this, but you could use expressions
public static object Add<T,T2>(T a,T2 b)
{
var paramA = Expression.Parameter(typeof(T), "a");
var paramB = Expression.Parameter(typeof(T2), "b");
var body = Expression.Add(Expression.Convert(paramA, paramB.Type), paramB);
var add = Expression.Lambda<Func<T, T2, T2>>(body, paramA, paramB).Compile();
return add(a, b);
}
The assumptions it that it will try to convert to the second parameter type and return of that type.
Obviously you any class will need the appropriate operators
Given
public struct Test
{
// user-defined conversion from Fraction to double
public static implicit operator int(Test f)
{
return 10;
}
public static implicit operator Test(int i)
{
return new Test();
}
// overload operator *
public static Test operator +(Test a, Test b)
{
return new Test();
}
}
Example
Console.WriteLine(Add(1, 2));
Console.WriteLine(Add(1, 2.0));
Console.WriteLine(Add(1, new Test()));
Refelction can be used to walk the properties of both objects, check for name equivalency and numeric data type, then amend property values in a totally generic way:
public static void AddObjects(object oFrom, object oTo)
{
if (oFrom != null && oTo != null)
{
foreach (System.Reflection.PropertyInfo f in oFrom.GetType().GetProperties())
{
if ((oTo).GetType().GetProperty(f.Name) != null)
{
try
{
string sType = f.GetType().ToString().ToLower();
if (sType==("int") )
{
oFrom.GetType().GetProperty(f.Name).SetValue(oFrom, (int)(f.GetValue(oFrom)) + (int)(f.GetValue(oTo)));
}
if (sType=="int32" )
{
oFrom.GetType().GetProperty(f.Name).SetValue(oFrom, (Int32)(f.GetValue(oFrom)) + (Int32)(f.GetValue(oTo)));
}
if (sType==("int64") )
{
oFrom.GetType().GetProperty(f.Name).SetValue(oFrom, (Int64)(f.GetValue(oFrom)) + (Int64)(f.GetValue(oTo)));
}
// keep adding for all numeirc types. maybe theres a better way?
}
catch (Exception ex)
{ }
}
}
}
}

How to detect actual type of an expression result? [duplicate]

I have a method that accepts a Expression<Func<T, object>> instance. I want to get at the actual data type being returned by a specific expression instance, rather than object.
I can get it to work for direct property references, so if I pass in the expression x => x.IntegerProperty I can get a Type reference for an integer. This approach requires converting it to a MemberExpression.
However, I can't get it to work for arbitrary expressions. For instance, if the expression is x => x.IntegerProperty.ToString() I want to get a Type reference for a string. I can't compile this to a MemberExpression, and if I just .Compile() it and check the return type I get "object".
How can I look at the specific expression instance and derive the actual return type?
Something like this might do the trick. It probably doesn't cover every possibility, but it's a start.
public static Type GetObjectType<T>(Expression<Func<T, object>> expr)
{
if ((expr.Body.NodeType == ExpressionType.Convert) ||
(expr.Body.NodeType == ExpressionType.ConvertChecked))
{
var unary = expr.Body as UnaryExpression;
if (unary != null)
return unary.Operand.Type;
}
return expr.Body.Type;
}
While not impossible, this is particularly difficult. It would require walking the expression tree and doing some potentially complex logic. For example, what would you want to see if I passed in the following expression?
Func<bool, object> expr = switch => switch ? 1 : "False";
This method could either return an int or a string.
Now, you might be able to make more headway by offloading some of this logic on the compiler. You could change your method parameter from Func<T, object> to Func<T, TReturn> and use typeof(TReturn) within the method to determine what the compiler decided the return type of the expression was.
Of course, in the case of my example, you'll still be working against object. But, your example of x => x.IntegerProperty.ToString() will yield string, which is what you're looking for.
Bit of a cheeky way (and it involves actually invoking the Func), but you can do this:
using System;
class Program
{
static Func<T,object> MakeFunc<T>()
{
return x => 23;
}
static Type GetReturnType<T>(Func<T,object> f)
{
return f(default(T)).GetType();
}
static void Main(string[] args)
{
Type t = GetReturnType(MakeFunc<string>());
Console.WriteLine(t);
}
}
It's not guaranteed to work in all situations, I should add - particularly if the default(T) isn't a valid parameter to the Func. But it's a potential starting point at least.

Why Resharper can't tell initialization is used

I am writing unit-tests while I've stumbled upon following suggestion by Resharper.
Value assigned is not used by any execution path.
in the following code snipet.
[Test]
[TestCase((int)OddsRoundingModes.Floor)]
public void GetBaseOddsRoundingMode_WithCorrectRoundingMode_ShouldReturnCorrectRoundingMode(int oddsRoundingMode)
{
// Arrange
var oddsRoundingModeStr = oddsRoundingMode.ToString(); // <-- suggestion here
var mock = new Mock<IConstantsStorage>();
var oddsRoundingConfiguration = new OddsRoundingConfiguration(mock.Object);
mock.Setup(h => h.TryGetConstant(It.IsAny<string>(), It.IsAny<int>(), out oddsRoundingModeStr))
.Returns(true);
// Act
var roundingMode = oddsRoundingConfiguration.GetBaseOddsRoundingMode(0);
// Assert
Assert.AreNotEqual(roundingMode, OddsRoundingModes.None);
}
But then when I change this to be not initialized at declaration, the mock is not properly setup and test fails, because oddsRoundingModeStr is not initialized and the mock return it as null.
Why can't Resharper see this?
EDIT:
public bool TryGetConstant(string name, int siteId, out string value)
{
value = RetrieveConstant(_constantsModel, name, siteId);
return value != null;
}
private string RetrieveConstant<T>(IConstantsModel<T> model, string constName, int siteId)
where T : IConstant, new()
{
if (model.Constants.TryGetValue(constName, out List<T> values))
{
var constant = values.FirstOrDefault(v => v.Name == constName && v.SiteIds.Contains(siteId));
if (constant != null)
{
return constant.ConstantValue;
}
}
return null;
}
Following normal C# semantics the value you initialize that variable to is irrelevant, since out can't read the data before having assigned a new value to it. Thus the resharper notice is appropriate.
I see several ways non standard semantics could be achieved using this code:
out is a decorated ref at the CLR level. So low level code could treat it as equivalent to ref.
void Main()
{
Ref r = R;
Out o = (Out)Delegate.CreateDelegate(typeof(Out), null, r.Method);
int i = 2;
o(out i);
i.Dump();
}
delegate void Out(out int x);
delegate void Ref(ref int x);
void R(ref int x)
{
x++;
}
Setup takes delegate and then uses private reflection on the closure object.
Setup takes an Expression<T>, i.e. a syntax tree of the lambda and interprets the expression in non standard ways.
In this context, the lambda expression is not C# code intended to be executed, but essentially a DSL describing how to setup the mock.
Option 3 seems the most likely
Setup accepts expression tree - and Moq analyzes that expression tree to create a moq. In this case you are basically saying that Moq should create implementation of IConstantsModel which accepts any string, any int, returns true and returns value you provide in oddsRoundingModeStr as out parameter. So when analyzing this expression tree, Moq will extract actual value of oddsRoundingModeStr (which is captured and stored in a field of compiler-generated class) and indeed will use it. Resharper is just unable to realize this, so provides a warning as usual.
Small example of how out variable value can be extracted from expression tree:
class Program {
static void Main(string[] args) {
int result = 2; // gives warning from your question
var back = ExtractOutValue(s => int.TryParse(s, out result));
Debug.Assert(back == result);
}
static int ExtractOutValue(Expression<Action<string>> exp) {
var call = (MethodCallExpression)exp.Body;
var arg = (MemberExpression) call.Arguments[1];
return (int) ((FieldInfo)arg.Member).GetValue(((ConstantExpression)arg.Expression).Value);
}
}

How to pass an arbitrary function with some bound parameters to another function?

I have a generic function CallLater that should accept an arbitrary other function and possibly call it later with some parameters. All kind of functions should be supported - static, instance, private, public. Parameters are analyzed and constructed dynamically in CallLater with the help of reflection. However, some of them may need to be bound to fixed values before passing the function to the CallLater.
For example:
void CallLater(Delegate d) {
// Expects a function that returns string and has one argument of arbitrary type.
if (d.Method.GetParameters().Length == 1 &&
d.Method.ReturnType == typeof(string)) {
object param1 = Activator.CreateInstance(d.Method.GetParameters()[0].ParameterType);
Console.WriteLine((string)d.DynamicInvoke(param1));
}
}
// Has one extra float parameter.
string MyFunc(int a, float b) { ... }
My idea was to do something like that:
float pi = 3.14f;
CallLater(delegate(int a) { return MyFunc(a, pi); });
But this doesn't work as compiler complains:
Error CS1660: Cannot convert `anonymous method' to non-delegate type `System.Delegate' (CS1660) (test-delegate)
What is the correct approach to achieve my goal?
P.S. Please do not offer the solution to declare a fixed delegate type as CallLater is way more complex and may support variable number of arguments too.
P.P.S. It might be that my solution is Func, but I wasn't able to use it on Mono so far.
You can always redeclare Func yourself:
public delegate TReturn FFunc<TArg,TReturn>(TArg arg);
Which you can use thusly:
float pi = 3.14f;
CallLater((FFunc<int,string>)(delegate(int a) { return MyFunc(a, pi); }));
I'd suggest using anonymous functions in which you call the method you want to execute. These are executed later when the anonymous method is executed.
private static void ExecuteBoolResult(Func<bool> method)
{
bool result = method();
if (!result)
{
throw new InvalidOperationException("method did not return true");
}
}
CheckBoolResult(() => AnotherFunction("with ", 3, " parameters"));
CheckBoolResult(() => AnotherFunction(2, "parameters"));

Calling a generic method with T type parameter

I am trying to build a method that will take a variety of numeric types and preprocess them for a second method. I am not sure if I should be simply overloading or using a generic method. I tried to use a generic method but the method does not seem to recognize the parameter type. The code is below. Can someone please explain to me whether it is better to overload or use a generic method in this case? Also, if I wanted to use a generic method to do this, how could I make it work? Thank you very much.
public static class math
{
public static int nextpow2<T>(T a)
{
double w;
if ( a.GetType() is sbyte ||
a.GetType() is byte ||
a.GetType() is short ||
a.GetType() is ushort ||
a.GetType() is int ||
a.GetType() is uint ||
a.GetType() is long ||
a.GetType() is ulong ||
a.GetType() is float ||
a.GetType() is double ||
a.GetType() is decimal
) w = (double)Convert.ChangeType(a, typeof(double));
else
throw new System.ArgumentException("Internal error in nextpow2: argument a is not a number!");
return _nextpow2(w);
}
private static int _nextpow2(double a)
{
double index = Math.Abs(a);
int p = (index > 1) ? (int)Math.Ceiling( Math.Log( index, 2.0) ) : 0;
return p;
}
I am calling the method as follows:
int indx = 0;
int p = math.nextpow2(indx);
The code fails to compile. I get the following error:
Internal error in nextpow2: argument a is not a number!
Can someone please explain what I am doing wrong? Thank you.
Can someone please explain what I am doing wrong?
Sure. You're checking whether a Type object is an sbyte, or a byte, etc. You're not checking whether the type represents the type of sbyte etc... you're asking whether the value is an sbyte. That's never, ever the case. (Which is why you're getting a compile-time error.)
You could use:
if (a.GetType() == typeof(byte) ||
// etc)
But I probably wouldn't. I wouldn't make this a generic method at all. If you really want the functionality, I'd write:
private static readonly HashSet<Type> ValidTypes = new HashSet<Type>
{
typeof(sbyte), typeof(byte), /* etc */
};
public static double ConvertToDouble(object x)
{
if (x == null)
{
throw new ArgumentNullException("x");
}
if (!ValidTypes.Contains(x.GetType())
{
throw new ArgumentException("...");
}
return Convert.ChangeType(x, typeof(double));
}
Note how this is doing one thing: converting the argument to double. There's no point in making it then call _nextpow2 - it's easy enough for the caller to do that if they want to.
Additionally, you've written two contradictory things:
The code fails to compile. I get the following error:
Internal error in nextpow2: argument a is not a number!
If it fails to compile (which is what I'd expect, btw) then you can't be running the code, which means you can't be getting the exception. You need to differentiate between compile-time errors like this:
warning CS0184: The given expression is never of the provided ('sbyte') type
and execution-time exceptions.
Also, both your class and method names violate normal .NET naming conventions.
You can either say
a is sbyte
or say
a.GetType() == typeof(sbyte)
but it makes no sense to mix it into a.GetType() is sbyte. You should get a compiler warning about that! For a.GetType() will be an object which derives from System.Type (actually it will be System.RuntimeType), and therefore it can never derive from sbyte (since sbyte is sealed, being a struct, and sbyte itself derives only from ValueType and Object).
A better solution than a generic method, is to have:
public static int Nextpow2(double a)
{
...
}
All numereric types except decimal are implicitly convertible to double. So with the above signature, you can use it the way you want:
int indx = 0;
int p = math.Nextpow2(indx);

Categories

Resources