I'm trying to pass in a custom MethodInfo to the Expression.AndAlso and OrElse factory methods (which are for the && and || operators, respectively). These operators use short circuiting, which makes this difficult, but normally the & and | operators (along with the true and false operators) are used. However, the MSDN documentation for Expression.AndAlso/OrElse doesn't mention the true or false operators.
For testing, I've declared a method that uses a normal & operator on two ints:
public static int And(int a, int b) {
return a & b;
}
Note that the return type must be int rather than bool to avoid an exception.
I then construct the expression:
var expr = Expression.AndAlso(
Expression.Constant(0),
Expression.Constant(5),
new Func<int, int, int>(And).Method
);
This results in an exception:
The user-defined operator method 'And' for operator 'AndAlso' must have associated boolean True and False operators.
Strangely, the error is also thrown if I use a custom struct that has the true and false operators. I can avoid it if the struct overloads the & operator and I pass in that overload, but not if I pass in a different method. Other non-short-circuiting operators work with custom methods though.
The problem is that I don't know how to pass methods for the true and false operators in. I first thought I could maybe combine them as delegates, but the different methods have incompatible signatures. Is there any way to pass these methods in?
The bigger picture
I'm building a system for interpreting expressions to support ahead-of-time compilation. It supports using a custom method for the AndAlso/OrElse operators, currently by taking a custom Func<InterpretedExpression, InterpretedExpression, object> (which works as the expressions are interpreted rather than compiled). This could easily be changed if it causes problems (which would be due to it not having accessible true and false methods).
Note: I'm using Visual Studio's C# Interactive window for testing, but ultimately need to support .NET 3.5 (though information for newer versions is still helpful and appreciated).
The problem is that I don't know how to pass methods for the true and false operators in. I first thought I could maybe combine them as delegates, but the different methods have incompatible signatures. Is there any way to pass these methods in?
The short answer is no, you can't.
Looking at the reference source implementation (unfortunately, it should really be in the documentation), looks like the passed method has the following constraints:
(1) It should be a static non generic method with signature
static T Method(T arg0, T arg1);
where T cannot be an open generic type.
(2) The declaring type of the method must have operators true and false defined.
Since operators true and false require the argument type to be the same as the declaring type, this combined with (1) really constraints the usage to class/struct T declaring the static method and true and false operators.
In other words, a method with bitwise & / | operator semantics without actually overloading those operators.
So it can be used only for types like this:
public struct IntWrapper
{
public readonly int Value;
public IntWrapper(int value) { Value = value; }
public static IntWrapper And(IntWrapper a, IntWrapper b) { return new IntWrapper(a.Value & b.Value); }
public static bool operator true(IntWrapper x) { return x.Value != 0; }
public static bool operator false(IntWrapper x) { return x.Value == 0; }
}
with usage:
var expr = Expression.AndAlso(
Expression.Constant(new IntWrapper(0)),
Expression.Constant(new IntWrapper(5)),
new Func<IntWrapper, IntWrapper, IntWrapper>(IntWrapper.And).Method
);
This I guess limits more general usage you are after.
Related
I am using a 3rd party tool (Unity3d), where one of the fundamental base classes overloads the == operator (UnityEngine.Object).
The overloaded operator's signature is:
public static bool operator == (UnityEngine.Object x, UnityEngine.Object y)
Does the order in which the comparison is made have any effect on whether this overloaded operator is used ?
To illustrate, should both of these use the overloaded operator and return the same result ?
// initialize with some value
UnityEngine.Object a = ....
Debug.Log(a == null);
Debug.Log(null == a);
The reason i'm asking is because i'd like to (sometimes) avoid this overloaded behaviour (use the default == operator), and was wondering whether flipping the order would assist in that ?
(There could be another option - casting the operands to System.object, but I am not 100% sure that works).
Well, it's possible that the two calls wouldn't be the same, if the operator had been overloaded badly. Either there could be one overload, and it could be written in a way which compares the operands asymmetrically, or the two statements could call different overloads.
But assuming it's been overloaded properly, that should be absolutely fine. That's if you want to call the overloaded operator, of course. In situations where you don't, I'd make that clear using ReferenceEquals.
I would personally recommend the if (a == null) approach, as I find it easier to read (and I believe many others do too). The "yoda" style of if (null == a) is sometimes used by C programmers who fear typos, where if (a = null) would be an assignment and a valid statement... albeit with a warning in decent C compilers.
Here's an example of a badly implemented set of overloads, where the operand order matters, because null is convertible to both string and Test:
using System;
class Test
{
public static bool operator ==(Test t, string x)
{
Console.WriteLine("Test == string");
return false;
}
public static bool operator !=(Test t, string x)
{
Console.WriteLine("Test != string");
return false;
}
public static bool operator ==(string x, Test t)
{
Console.WriteLine("string == Test");
return false;
}
public static bool operator !=(string x, Test t)
{
Console.WriteLine("string != Test");
return false;
}
static void Main(string[] args)
{
Test t = null;
Console.WriteLine(t == null);
Console.WriteLine(null == t);
}
}
Now that the question has been updated, we can tell that's not the case... but the implementation could still be poor. For example, it could be written as:
public static bool operator == (UnityEngine.Object x, UnityEngine.Object y)
{
// Awful implementation - do not use!
return x.Equals(y);
}
In that case, it will fail with a NullReferenceException when x is null, but succeed if x is non-null but y is null (assuming Equals has been written properly).
Again though, I'd expect that the operator has been written properly, and that this isn't a problem.
UPDATE after updating the question:
If you want to avoid calling the overloaded function when comparing to null, use ReferenceEquals:
if(a.ReferenceEquals(null)) ...
OLDER ANSWER, RENDERED OBSOLETE AND ALSO WRONG BY #Jon Skeet...
According to this, overload resolution of binary operator with X and Y as arguments is done by first taking the union of all operators defined by X and by Y.
So a==b results in exactly the same overload resolution as b==a.
The link is from 2003, but I doubt Microsoft has changed something since, it would have broken a lot of older code.
Update: Although I witnessed this behaviour in prior versions of Unity, I couldn't reproduce it in a test I performed right after writing this answer. May be Unity changed the == operator behaviour, or behaviour of implicit conversion of UnityEngine.Object to bool; however, I would still advocate using the overridden == operator instead of trying to avoid it.
The way Unity in particular overrides == operator is very frustrating, but also fundamental for how you have to work with the engine. After the UnityObject gets destroyed, by calling Destroy (some time after the call) or DestroyImmediate (immediately after the call, as the name would suggest), the comparison of this object to null returns true, even though it's not a null reference.
It's completely unintuitive for C# programmers, and can create a lot of truly WTF moments before you figure this out. Take this, for example:
DestroyImmediately(someObject);
if (someObject)
{
Debug.Log("This gets printed");
}
if (someObject != null)
{
Debug.Log("This doesn't");
}
The reason I'm explaining that is because I perfectly understand your desire to avoid this strange overridden behaviour, especially if you had C# experience before working with Unity. However, as with a lot of other Unity-specific stuff, it might actually be better to just stick to the Unity convention instead of trying to implement everything in the C#-correct way.
What are the precise rules for overload resolution with == between two expressions of delegate type?
Consider the following code (where using System; is needed):
static class ProgramA
{
static void TargetMethod(object obj)
{
}
static void Main()
{
Action<object> instance1 = TargetMethod;
Action<object> instance2 = TargetMethod;
Action<string> a1 = instance1;
Action<Uri> a2 = instance2;
Console.WriteLine((object)a1 == (object)a2);
Console.WriteLine((Delegate)a1 == (Delegate)a2);
Console.WriteLine((Action<object>)a1 == (Action<object>)a2);
Console.WriteLine(a1 == a2); // warning CS0253: Possible unintended reference comparison; to get a value comparison, cast the right hand side to type 'System.Action<string>'
}
}
Explanation:
instance1 and instance2 are two separate instances of the same run-time type, the generic Action<in T> which is contravariant in T. Those instances are distinct but Equals since they the have same targets.
a1 and a2 are the same as instance1 and instance2, but because of the contravariance of Action<in T> there exist implicit reference conversions from Action<object> to each of Action<string> and Action<System.Uri>.
Now, the C# Language Specification has (among other overloads) these operator ==:
bool operator ==(object x, object y); // §7.10.6
bool operator ==(System.Delegate x, System.Delegate y); // §7.10.8
The current Visual C# compiler realizes the first one by simply checking if the references are the same (the IL does not actually call a mscorlib method like object.ReferenceEquals, but that would give the same result), while it realizes the second one by calling Delegate.op_Equality method which looks like a "user-defined" operator inside that assembly even when it is defined by the C# Language Spec, so is maybe not "user-defined" in the sense of the spec(?).
Note that §7.10.8 is a little confusing because it says "Every delegate type implicitly provides the following predefined comparison operator[s]" and then gives the operator with the (System.Delegate, System.Delegate) signature. That is just one operator, not one for "every" delegate type? This seems important for my question.
It is not surprising that the three first WriteLine write False, True and True, respectively, given what I said above.
Question: But why does the fourth WriteLine lead to the (object, object) overload being used?
There does exist an implicit reference conversion from Action<> (or any other delegate type) to System.Delegate, so why can't that be used here? Overload resolution should prefer that over the (object, object) option.
Of course, there are no implicit conversions between Action<string> and Action<Uri>, but why is that relevant? If I create my own class MyBaseClass containing a user-defined operator ==(MyBaseClass x, MyBaseClass y) and I create two unrelated deriving classes, then my == operator will still be used (left and right operand not convertible to each other but both convertible to MyBaseClass).
Just for completeness, here is the analogous example with covariance (Func<out TResult>) instead of contravariance:
static class ProgramF
{
static string TargetMethod()
{
return "dummy";
}
static void Main()
{
Func<string> instance1 = TargetMethod;
Func<string> instance2 = TargetMethod;
Func<ICloneable> f1 = instance1;
Func<IConvertible> f2 = instance2;
Console.WriteLine((object)f1 == (object)f2);
Console.WriteLine((Delegate)f1 == (Delegate)f2);
Console.WriteLine((Func<string>)f1 == (Func<string>)f2);
Console.WriteLine(f1 == f2); // warning CS0253: Possible unintended reference comparison; to get a value comparison, cast the right hand side to type 'System.Func<System.ICloneable>'
}
}
A question related to my question above is, where in the C# Language Specification does it say that this shall be illegal:
Func<string> g1 = ...;
Func<Uri> g2 = ...;
Console.WriteLine(g1 == g2); // error CS0019: Operator '==' cannot be applied to operands of type 'System.Func<string>' and 'System.Func<System.Uri>'
I can see that the compiler figured out that no type can ever inherit from both string and Uri (unlike the pair ICloneable and IConvertible), and so this (if it were legal) could only become true if both variables were null, but where does it say that I am not allowed to do this? In this case it would not matter if the compiler chose operator ==(object, object) or operator ==(Delegate, Delegate) since, as I said, it comes down to checking if both are null references, and both overloads do that in the same way.
Question: But why does the fourth WriteLine lead to the (object, object) overload being used?
Because it's the only choice for the compiler :-)
Cannot apply operator '==' to operands of type 'System.Func<System.ICloneable>' and 'System.Func<System.IConvertable>'
candidates are:
bool==(System.Delegate, System.Delegate)
bool==(System.Func<System.ICloneable>, System.Func<System.ICloneable>)
bool==(System.Func<System.IConvertable>, System.Func<System.IConvertable>)
so using your (object, object) is the best choice the compiler finds.
same for the Actions
Cannot apply operator '==' to operands of type 'System.Action<string>' and 'System.Action<System.Uri>'
candidates are:
bool==(System.Delegate, System.Delegate)
bool==(System.Action<string>, System.Action<string>)
bool==(System.Action<System.Uri>, System.Action<System.Uri>)
This question already has answers here:
C#, Flags Enum, Generic function to look for a flag
(11 answers)
Closed 6 years ago.
My application defines several enums that include the [Flags] attribute.
I wanted to write a small utility method to check if a flag was set for any of those enums and I came up with the following.
protected static bool IsFlagSet<T>(ref T value, ref T flags)
{
return ((value & flags) == flags);
}
But this gives me the error "Operator '&' cannot be applied to operands of type 'T' and 'T'".
Can this be made to work?
The Enum class already has a utility function: Enum.HasFlag(Flag f), see the example on MSDN
if (petsInFamily.HasFlag(Pet.Dog))
familiesWithDog++;
Note: This was introduced in C# 4.
And while it's very readable it may have some performance issues.
I understand that my answer is too late, but I found really amazing solution of this problem.
Starting from .Net 4 we can use dynamic types in C#. You method can be rewritten:
protected static bool IsFlagSet<T>(T value, T flags)
{
dynamic a = value;
dynamic b = flags;
return ((a & b) == flags);
}
Idea behind that dynamic allows you postpone to runtime if method/operator supported by type T. So if & is defined for T then runtime is success.
& is an operator on a class type. Which means that the class T has to have a method that overloads the operator &.
.Net can't expect that every class will have it. So it fails.
What you can do, is make a base class, that declares the operator overload as a method.
Then use Constraints to declare that T uses that base class:
protected static bool IsFlagSet<T> where T: BaseclassWithAnd (ref T value, ref T flags)
{
return ((value & flags) == flags);
}
You must type-cast it to a type that defines the & operation.
protected static bool IsFlagSet<T>(ref T value, ref T flags)
{
return ((Convert.ToInt32(value) & Convert.ToInt32(flags)) == Convert.ToInt32(flags));
}
The reason of the error is that you can't restric generic type as "have operator X defined for T,T". As result C# has to assume that there is no operator X defined for T,T and shows an error.
This is behavior often discussed in relation to == operator - i.e. Can't operator == be applied to generic types in C#?, but applies to all operators.
For full list of possible constrints see - http://msdn.microsoft.com/en-us/library/d5x73970(v=VS.100).aspx, note that there is no constraint for Enum (that would be useful for your scenario specifically) nor for types with operator X defined.
The Type class has a method IsAssignableFrom() that almost works. Unfortunately it only returns true if the two types are the same or the first is in the hierarchy of the second. It says that decimal is not assignable from int, but I'd like a method that would indicate that decimals are assignable from ints, but ints are not always assignable from decimals. The compiler knows this but I need to figure this out at runtime.
Here's a test for an extension method.
[Test]
public void DecimalsShouldReallyBeAssignableFromInts()
{
Assert.IsTrue(typeof(decimal).IsReallyAssignableFrom(typeof(int)));
Assert.IsFalse(typeof(int).IsReallyAssignableFrom(typeof(decimal)));
}
Is there a way to implement IsReallyAssignableFrom() that would work like IsAssignableFrom() but also passes the test case above?
Thanks!
Edit:
This is basically the way it would be used. This example does not compile for me, so I had to set Number to be 0 (instead of 0.0M).
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Parameter)]
public class MyAttribute : Attribute
{
public object Default { get; set; }
}
public class MyClass
{
public MyClass([MyAttribute(Default= 0.0M)] decimal number)
{
Console.WriteLine(number);
}
}
I get this error:
Error 4 An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type
There are actually three ways that a type can be “assignable” to another in the sense that you are looking for.
Class hierarchy, interface implementation, covariance and contravariance. This is what .IsAssignableFrom already checks for. (This also includes permissible boxing operations, e.g. int to object or DateTime to ValueType.)
User-defined implicit conversions. This is what all the other answers are referring to. You can retrieve these via Reflection, for example the implicit conversion from int to decimal is a static method that looks like this:
System.Decimal op_Implicit(Int32)
You only need to check the two relevant types (in this case, Int32 and Decimal); if the conversion is not in those, then it doesn’t exist.
Built-in implicit conversions which are defined in the C# language specification. Unfortunately Reflection doesn’t show these. You will have to find them in the specification and copy the assignability rules into your code manually. This includes numeric conversions, e.g. int to long as well as float to double, pointer conversions, nullable conversions (int to int?), and lifted conversions.
Furthermore, a user-defined implicit conversion can be chained with a built-in implicit conversion. For example, if a user-defined implicit conversion exists from int to some type T, then it also doubles as a conversion from short to T. Similarly, T to short doubles as T to int.
This one almost works... it's using Linq expressions:
public static bool IsReallyAssignableFrom(this Type type, Type otherType)
{
if (type.IsAssignableFrom(otherType))
return true;
try
{
var v = Expression.Variable(otherType);
var expr = Expression.Convert(v, type);
return expr.Method == null || expr.Method.Name == "op_Implicit";
}
catch(InvalidOperationException ex)
{
return false;
}
}
The only case that doesn't work is for built-in conversions for primitive types: it incorrectly returns true for conversions that should be explicit (e.g. int to short). I guess you could handle those cases manually, as there is a finite (and rather small) number of them.
I don't really like having to catch an exception to detect invalid conversions, but I don't see any other simple way to do it...
Timwi's answer is really complete, but I feel there's an even simpler way that would get you the same semantics (check "real" assignability), without actually defining yourself what this is.
You can just try the assignment in question and look for an InvalidCastException (I know it's obvious). This way you avoid the hassle of checking the three possible meanings of assignability as Timwi mentioned. Here's a sample using xUnit:
[Fact]
public void DecimalsShouldReallyBeAssignableFromInts()
{
var d = default(decimal);
var i = default(i);
Assert.Throws<InvalidCastException)( () => (int)d);
Assert.DoesNotThrow( () => (decimal)i);
}
What you are looking for is if there's an implicit cast from the one type to the other. I would think that's doable by reflection, though it might be tricky because the implicit cast should be defined as an operator overload which is a static method and I think it could be defined in any class, not just the one that can be implicitly converted.
In order to find out if one type can be assigned to another, you have to look for implicit conversions from one to the other. You can do this with reflection.
As Timwi said, you will also have to know some built-in rules, but those can be hard-coded.
It actually happens to be the case that the decimal type is not "assignable" to the int type, and vice versa. Problems occur when boxing/unboxing gets involved.
Take the example below:
int p = 0;
decimal d = 0m;
object o = d;
object x = p;
// ok
int a = (int)d;
// invalid cast exception
int i = (int)o;
// invalid cast exception
decimal y = (decimal)p;
// compile error
int j = d;
This code looks like it should work, but the type cast from object produces an invalid cast exception, and the last line generates a compile-time error.
The reason the assignment to a works is because the decimal class has an explicit override on the type cast operator to int. There does not exist an implicit type cast operator from decimal to int.
Edit: There does not exist even the implicit operator in reverse. Int32 implements IConvertible, and that is how it converts to decimal
End Edit
In other words, the types are not assignable, but convertible.
You could scan assemblies for explicit type cast operators and IConvertible interfaces, but I get the impression that would not serve you as well as programming for the specific few cases you know you will encounter.
Good luck!
public static T IsNull<T>(object value, T defaultValue)
{
return ((Object.Equals(value,null)) | (Object.Equals(value,DBNull.Value)) ?
defaultValue : (T)value);
}
public static T IsNull<T>(object value) where T :new()
{
T defaultvalue = new T();
return IsNull(value, defaultvalue);
}
Have tested, and can use against data objects, classes and variables.
Just want to know if there is better way to go about this.
It looks like you're trying to duplicate the null coalesce operator:
var foo = myPossiblyNullValue ?? defaultValue;
First off, the method name is wrong. You imply that the result of the function is a boolean that is true exactly if the given value is null. In fact, that’s not the case. GetValueOrDefault might be a better name.
Secondly, you’re merely replicating the behaviour of the null coalesce operator, as mentioned by others.
Thirdly, your conditional is odd:
Object.Equals(value,null)) | (Object.Equals(value,DBNull.Value)
Why Object.Equals instead of ==? Better yet, use Object.ReferenceEquals since that makes it clear that you’re interested in reference equality. Also, you’re using the bitwise-or operator (|) which is semantically wrong in this context, although it happens to yield the right value. You want the boolean-or operator ||. (Also, inconsistency: why do you sometimes write object and other times Object?)
Finally, using type object instead of a generic type isn’t necessarily a good solution. It would be better to create overloads for generic reference and value types: this avoids boxing in the value types. It also means that you don’t have to specify the type explicitly in your second overload since it can be deduced from the method argument.
public static bool IsNull<T>(object value)
{
return object == default(T);
}
[Edited]
The following (non-generic) should work.
public static bool IsNull(object value)
{
return value == null;
}
Any value type will get boxed (i.e. non-null). Ref types will just be passed by pointer.