C# dynamic casting during operator evaluation - c#

I currently have a user defined type
class MyType {
double x;
double y;
double z;
//This class has operator overloading implemented
public static MyType operator + (double a,MyType b){
...
}
}
At some point later I will have an array (object[]) some of them double and some MyType. I would like to do evaluation over them but compiler is not allowing operator '+' to be applied to type object and object. What should I do here?

When resolving a + in code the compiler needs to bind it to a specific operation. The type object has no + operation and the compiler has no idea that the underlying types are double and MyType and hence the compiler errors out.
In order to fix this you will need to either
statically convert the elements to double and MyType so the compiler can properly bind the + operator
use dynamic and rely on the runtime binding to the correct operator+.
Here is an example of the latter method.
class MyType {
double _value;
internal MyType(double value) {
_value = value;
}
public static MyType operator +(double left, MyType right) {
return new MyType(left + right._value);
}
public static MyType operator +(MyType left, double right) {
return new MyType(left._value + right);
}
public static MyType operator +(MyType left, MyType right) {
return new MyType(left._value + right._value);
}
public static implicit operator MyType(double other) {
return new MyType(other);
}
}
class Program
{
static void Main(string[] args) {
object[] them = new object[] {
42,
new MyType(13),
12,
new MyType(12)
};
dynamic all = them;
MyType sum = 0;
foreach (dynamic element in all) {
sum += element;
}
Console.WriteLine(sum);
}
}

Honestly, I would create a MyType constructor that took a single double parameter, and use that to convert each double to a MyType, so that you could just use a MyType[] (or List<MyType>).
I understand that's really not what you're asking, but you'd still be able to handle the MyType creation such that the addition will perform properly, and you'd be more type-safe with your array.

You should be more specific with your types - the reason you cannot add is because object could be anyting in the system.
Is there any way that you can change object for a more specific type?
If it absolutely has to be object then you will have to evaluate at run-time using casts or the as operator or some similar mechanism.
eg
public static MyType operator +(object o, MyType b)
{
MyOtherType mot = o as MyOtherType;
if(o!=null)
...
but be in no doubt that your solution here raises questions about your design choices

Related

Can Boolean operators ever produce a non-Boolean result?

Please note, this question is not about the correctness of this style/convention, only about the use of Boolean operators. Just wanted to mention the style to give context.
Microsoft's C# Coding Conventions states that implicit typing is allowed "for local variables when the type of the variable is obvious from the right side of the assignment."
In the following code:
bool x = X();
bool y = Y();
var z = x && y;
Does the Boolean operator in the declaration of z make its type "obvious"? In other words, is there any situation in C# where && can be used with an x and y that are not Boolean, and produce a result that is not Boolean?
Are && and || guaranteed to return a boolean? No. Will they almost always result in a boolean? Most definitely.
By way of a counter example for && returning a non-boolean, consider the following:
public class Foo
{
public int Val { get; }
public Foo(int val) { Val = val; }
public static bool operator true(Foo val) {
return val.Val > 0;
}
public static bool operator false(Foo val) {
return val.Val <= 0;
}
public static Foo operator &(Foo left, Foo right) {
return new Foo(left.Val & right.Val);
}
public static Foo operator |(Foo left, Foo right) {
return new Foo(left.Val | right.Val);
}
}
Now we have a class that has indirectly overloaded the && and || operators, and they return type Foo.
The specification has this to say about user defined && and || operators:
When the operands of && or || are of types that declare an applicable user-defined operator & or operator |, both of the following must be true, where T is the type in which the selected operator is declared:
• The return type and the type of each parameter of the selected operator must be T. In other words, the operator must compute the logical AND or the logical OR of two operands of type T, and must return a result of type T.
• T must contain declarations of operator true and operator false.
Now, we evaluate the following:
var foo = new Foo(5) && new Foo(4);
foo is of Type Foo, with a Val of 4, as 5 & 4 is 4.
All of that said, I would not expect to see this kind of behavior outside of very specific circumstances.
Additionally, as the specification points out, the result of && or || must be the type of the parameters. In a bool && bool or bool || bool scenario, this should always be bool. So long as you're doing your logical operations on booleans (and not strange random non-boolean types) you should expect the result to be a bool.
Yes, it is possible for that to return something that is not a boolean as long as it can be evaluated as a boolean.
This requires you to overload the true and false operators, take this strange type:
public class MyStrangeType
{
public static readonly MyStrangeType Strange1 = new MyStrangeType(0);
public static readonly MyStrangeType Strange2 = new MyStrangeType(1);
private int myValue;
public int Value { get { return myValue; } }
private MyStrangeType(int value)
{
myValue = value;
}
public static bool operator true(MyStrangeType x) { return x.myValue == 1; }
public static bool operator false(MyStrangeType x) { return x.myValue != 1; }
public static MyStrangeType operator &(MyStrangeType x, MyStrangeType y)
{
return new MyStrangeType(3);
}
}
Now when you do something like this:
var result = MyStrangeType.Strange1 && MyStrangeType.Strange2;
result is not a boolean but a MyStrangeType.
Try it out!
public class Program
{
public static void Main()
{
var result = MyStrangeType.Strange1 && MyStrangeType.Strange2;
Console.WriteLine(result.GetType().FullName);
}
}
Outputs:
MyStrangeType
I could maybe misunderstood your question but this maybe could help to you or someone else.
There is "is" operator. You can check a veriable is a type of something.
For example;
var z = x is bool && y is bool;
You have two separate questions.
is there any situation in C# where && can be used with an x and y
that are not Boolean, and produce a result that is not Boolean?
This is shown by the other answers.
Does the Boolean operator in the declaration of z make its type "obvious"?
Yes, if x and y are bools. Since the && operator applied on boolean operands always returns a bool, which is defined in the specification. C# doesn't really allow variable return types for the same overload, except for the case of using the dynamic keyword. But then var is just inferred as dynamic as well.

C# : Convert an object to Boolean depending on a class variable

My class looks something like this:
public class Testclass
{
public int myValue;
}
In another context I want to simply check the value of myValue against 0.
So I would write:
Testclass tc = new Testclass();
tc.myValue = 13;
if (tc.myValue == 0)
{
}
How would it be possible to simplify this so that the Testclass object knows when it is compared to a boolean? (or used as a boolean value) to write:
Testclass tc = new Testclass();
tc.myValue = 13;
if (tc)
{
}
To be more precise, the Testclass will be the result of another method that is included in a library, so the code would look like this:
anotherClass ac =new anotherClass();
// if (ac.AMethod().myValue == 0)
// should be
if (ac.AMethod())
{
}
Where AMethod would look like this:
public Testclass AMethod()
{
return new Testclass();
}
[Edit at 2016-04-13]:
Like Dennis wrote, i am using
public static implicit operator bool(TestClass value)
to get the "Boolean Value" of my class. To be a bit more precise and to stick more to my real application i would like to change the signature to
public static implicit operator UInt64(FlexComDotNetFehler fehler)
public static implicit operator Boolean(FlexComDotNetFehler fehler)
So these two methods of class FlexComDotNetFehler return the internal UInt64 field in the first case as the real representation as UInt64and in the second one as a Boolean value, that is true, when the UInt64 value is > 0.
But now, when i code
FlexComDotNetFehler x;
FlexComDotNetFehler y;
if (x == y)
where x and y are both of type FlexComDotNetFehler
the compiler cant know if it should use the Boolean or the UInt64 operator.
So i wrote
if ((UInt64)x != (UInt64)y)
but then those two type casts are greyed out.
#Ɖiamond ǤeezeƦ: thanks for your reformatting and editing. But I think now i got i right?
Greetings Wolfgang
BTW is there a playground where i can test the formatting and its output? And how do i send private messages to other users?
Define implicit cast operator for TestClass:
class TestClass
{
public int myValue;
public static implicit operator bool(TestClass value)
{
// assuming, that 1 is true;
// somehow this method should deal with value == null case
return value != null && value.myValue == 1;
}
}
Also think about converting TestClass from class to structure (see this reference). If you'll decide to convert it, avoid mutable structures.
you can use extension methods to implement method you can use any time not only for this class Testclass
public static class IntExtension
{
public static bool IsBool(this int number)
{
bool result = true;
if (number == 0)
{
result = false;
}
return result;
}
}
and then yo can
if ((ac.AMethod()).IsBool())
{}

C# Operator Overloading, rewriting string?

I'm very fresh to C#
Currently learning Operator overloading
i'm trying to do something like this:
string val = 500; (I can't implicitly)
and then
Number n1 = val;
I manages to get the Number n1 = someintvalue, for instance:
Number n1 = 500;
like this:
public struct Number
{
public int Value { get; set; }
public Number(int Val)
{
Value = Val;
}
public static implicit operator Number(int num)
{
return new Number(num);
}
}
However, when trying to make Number n1 = val; (when val is a string)
I simply cant since the first line cant compile:
string val = 500;
and the following wont work:
public static implicit operator string(int A)
{
return new string(A);
}
because of 1 error which i can not understand
1)User-defined conversion must convert to or from the enclosing type
by the way i get the idea of op overload
underthis specific case of: return new Number(num);
I simply init the ctor
still need some more fundemental understanding
thx ahead!
I presume the function you quote is within the Number class. You have added a conversion operator from an int to a string within that class, which is not legal. You can only add operators that convert to or from the type they're defined in, such as:
public static implicit operator string(Number A)
{
return new string(A.Value);
}
which will fail because string does not have a constructor that takes an int. You could do:
public static implicit operator string(Number A)
{
return A.ToString();
}
But the standard way to "convert" to a string is to overload the ToString method, which the compiler often calls automatically when a conversion to string is requested:
public override string ToString()
{
return Value.ToString();
}

Overloading Primitive Operator (C#)

Is there a way I can overload primitives, for example addition with doubles? I want to automatically round the doubles whenever an operation is performed. My current code is this:
class Test{
public static double operator +(double x, double y){
return Math.Round(x + y)
}
}
but there's an unfortunate error that says "One of the parameters of a binary operator must be the containing type".
No, and this would be horrible. Users using your library would suddenly get different behaviors from their double variables!
You can write and use a wrapper object however:
public struct MyDouble
{
public double Value {get; set;}
public MyDouble(double initValue)
{
Value = initValue;
}
public static double operator +(MyDouble x, MyDouble y){
return Math.Round(x.Value + y.Value)
}
}
You can also make it castable to/from a double, among other options. This way users know they are using your object and won't be surprised when their math operations are rounded.
If you want to assign from a simple double, you would need to define an implicit operator, similar to that of Nullable<T> (source):
public static implicit operator MyDouble(double value) {
return new MyDouble(value);
}
You can't overload operators on primitive types. This would cause havoc in your codebase.
What you can do instead, is to create a simple wrapper around the primitive type, let's say RoundedDouble:
public struct RoundedDouble : IEquatable<RoundedDouble>, IComparable<RoundedDouble>
{
public readonly double Value;
public RoundedDouble(double value)
{
Value = Math.Round(value); // Or anything else
}
public static implicit operator RoundedDouble(double value)
{
return new RoundedDouble(value);
}
public static implicit operator double(RoundedDouble wrapper)
{
return wrapper.Value;
}
public int GetHashCode()
{
return Value.GetHashCode();
}
public bool Equals(object other)
{
if (other is RoundedDouble)
return ((RoundedDouble)other).Value == Value;
return false;
}
public string ToString()
{
return Value.ToString();
}
// Add your operators here, and implement the interfaces
}
This is a structure. It has the same value semantics as a double.
Extend it by adding the operators, and by implementing at least IEquatable<RoundedDouble> and IComparable<RoundedDouble>.

C# Generic Operators

I am trying to implement a generic operator like so:
class Foo
{
public static T operator +<T>(T a, T b)
{
// Do something with a and b that makes sense for operator + here
}
}
Really what I'm trying to do is gracefully handle inheritance. With a standard operator + in Foo, where T is instead "Foo", if anyone is derived from Foo (say Bar inherits Foo), then a Bar + Bar operation will still return a Foo. I was hoping to solve this with a generic operator +, but I just get a syntax error for the above (at the <) making me believe that such code is not legal.
Is there a way to make a generic operator?
No, you can't declare generic operators in C#.
Operators and inheritance don't really mix well.
If you want Foo + Foo to return a Foo and Bar + Bar to return a Bar, you will need to define one operator on each class. But, since operators are static, you won't get the benefits of polymorphism because which operator to call will be decided at compile-time:
Foo x = new Bar();
Foo y = new Bar();
var z = x + y; // calls Foo.operator+;
https://jonskeet.uk/csharp/miscutil/usage/genericoperators.html
static T Add<T>(T a, T b) {
//TODO: re-use delegate!
// declare the parameters
ParameterExpression paramA = Expression.Parameter(typeof(T), "a"),
paramB = Expression.Parameter(typeof(T), "b");
// add the parameters together
BinaryExpression body = Expression.Add(paramA, paramB);
// compile it
Func<T, T, T> add = Expression.Lambda<Func<T, T, T>>(body, paramA, paramB).Compile();
// call it
return add(a,b);
}
You can just define operator in a generic class Foo.
You can also create real generic operators, but C# compiler won't use them.
[System.Runtime.CompilerServices.SpecialName]
public static T op_Addition<T>(T a, T b) { ... }
You cannot declare generic operators in C# - I am not sure on the reasoning but assume it's a usefulness vs effort thing for the implementation team (I believe there might be a post on here with Jon Skeet discussing it, or perhaps on his blog when he discussed things he'd like to see in C#).
Indeed, you cannot even use operators with generics in C#.
This is because generics must be applicable for all possible types that could be provided. This is why you must scope the generic type to classes when you want to use == as below:
void IsEqual<T>(T x, T y) where T : class
{
return x == y;
}
Unfortunately you cannot do:
void Add<T>(T x, T y) where T : operator +
{
return x + y;
}
You might also be interested in this short summary article I came across.
Was searching for the same thing and google brought me here....
I wasn't too happy about the accepted answer and was looking for a workaround.
I managed to implement this using generics. Here is the Foo and Bar class:
class Foo
{
private int value;
public Foo(int x)
{
value = x;
}
public virtual int getVal()
{
return value;
}
}
class Bar : Foo
{
private int derivedValue;
public Bar(int x):base(x)
{
derivedValue = x;
}
public override int getVal()
{
return derivedValue;
}
}
Then a generic class containing the operators but restricted to type of Foo and derived from Foo:
class GenericOp<T> where T : Foo
{
private T value;
public GenericOp(T x)
{
value = x;
}
public static Foo operator +(GenericOp<T> a, GenericOp<T> b)
{
return new Foo(a.value.getVal() + b.value.getVal());
}
}
Some usage code showing you always get back a Foo as well as preventing you from mixing the types:
Foo f1 = new Foo(1);
Foo f2 = new Foo(2);
Bar b1 = new Bar(10);
Bar b2 = new Bar(20);
GenericOp<Foo> left = new GenericOp<Foo>(f1);
GenericOp<Foo> right = new GenericOp<Foo>(f2);
Foo res = left + right;
GenericOp<Bar> left1 = new GenericOp<Bar>(b1);
GenericOp<Bar> right1 = new GenericOp<Bar>(b2);
Foo res1 = left1 + right1;
GenericOp<Foo> left2 = new GenericOp<Foo>(f1);
GenericOp<Bar> right2 = new GenericOp<Bar>(b1);
//Foo res2 = left2 + right2; //this fails and rightfully so.
This is now possible in C# 11 via static abstract interface methods; for example:
public interface IMyInterface<T> where T : IMyInterface<T>
{
static abstract T operator +(T left, T right);
}
which you can then use via where T : IMyInterface<T> as:
class Bar
{
static T Add<T>(T x, T y, T z) where T : IMyInterface<T>
{
return x + y + z;
}
}
The problem, though, is that every T you want would need to implement IMyInterface<T>, which isn't possible for pre-defined types (like int, float, etc) which you don't control. The good news is that .NET 7 does this for you, for all the types you might think of, so in reality you don't need to define your own API; instead, you might use the system-defined interface INumber<T>:
static T Add<T>(T x, T y, T z) where T : INumber<T>
{
return x + y + z;
}

Categories

Resources