Behold the following example with System.Nullable<T> in C#.
int x = 5;
int? y = 3;
int? result = x + y; //no compiler warning
It makes sense that the compiler can figure out that T is an int, thus it can use the operator.
Also in
int x = 5;
int? y = 3;
bool result = x == y; //no compiler warning
it makes sense, if x was null, the expression would be false. The compiler doesn't mind.
Now I'm trying to create a lookalike Nullable<T> class. Let's call it Lookable<T>.
[Serializable]
public struct Lookable<T> where T : struct
{
public Lookable(T value)
{
Value = value;
}
public T Value { get; }
public override bool Equals(object other)
{
return other != null && Value.Equals(other);
}
public override int GetHashCode()
{
return Value.GetHashCode();
}
public override string ToString()
{
return Value.ToString();
}
public static implicit operator Lookable<T>(T value)
{
return new Lookable<T>(value);
}
public static explicit operator T(Lookable<T> value)
{
return value.Value;
}
}
The idea here is straight from .NET's source code. In my case I'm just omitting the HasValue property.
Now this example would work:
int x = 6;
Lookable<int> y = x;
Lookable<int> z = 4;
The compiler can infer the types here because of the implicit operator correct?
What I don't understand is that this example will make the compiler unhappy:
int x = 5;
Lookable<int> y = 3;
var result1 = x + y; //compile error
var result2 = x == y; //compile error
The compiler is giving me the message:
Operator cannot be applied to operands of type 'int' and 'Lookable<int>'.
Why not? And why is it possible with Nullable<T>? I can't find it anywhere in the source code. Would it also be possible for Lookable<T>?
The code for this isn't in Nullable<T> - it is in the C# compiler, in particular "lifted operators" in the specification, and how they apply specifically to System.Nullable<T>. The specification references are in this answer.
You cannot reproduce the Nullable<T> behaviour in your own types. It has special handling by both the compiler and the runtime (boxing, etc).
Related
I am trying to implement cartesian 2D integer coordinate system. I have managed to get +, -, * and / operators working. However, after implementing the == operator in the same way I am getting errors.
My struct is defined as follows:
public struct IntVector2 : IEquatable<IntVector2>
{
// properties
public int x { get; private set; }
public int y { get; private set; }
// constructors
public IntVector2(int x, int y)
{
this.x = x;
this.y = y;
}
// I have removed the XML documentation and operator definitions here
}
NB: I implemented .Equals and .GetHashCode according to the .NET guidelines. Hence the IEquateable<IntVector2>
I have also defined the following operators (and many more) within the struct body:
public static bool operator ==(IntVector2 a, Vector2 b)
{
return (a.x == b.x && a.y == b.y);
}
public static bool operator != (IntVector2 a, Vector2 b)
{
return !(a == b);
}
// Once again I removed the XML documentation
And the following overrides:
public override bool Equals(object obj)
{
if (!(obj is IntVector2))
{
return false;
}
IntVector2 intVect2 = (IntVector2)obj;
return (x == intVect2.x && y == intVect2.y);
}
public override int GetHashCode()
{
return (x * 31 + y);
}
In an effort to find a pre-existing answer, I investigated the following links:
Can't operator == be applied to generic types in C#?
https://coding.abel.nu/2014/09/net-and-equals/ --- info and
demonstration of equality operator being used
msdn.microsoft.com/en-us/library/c35t2ffz.aspx --- Equality operators
msdn.microsoft.com/en-us/library/7h9bszxx(v=vs.100).aspx --- MSDN
guidelines for implementing equality operators
All my other operators work fine, but when I try to compare the equality of 2 IntVector2s, I get errors. For example:
void Foo(IntVector2 intVectA, IntVector2 intVectB)
{
if (intVectA.Equals(intVectB))
{
IntVector2 C = intVectA + intVectB;
bool isEqual = intVectA == intVectB;
}
}
Gives the error
Operator '==' cannot be applied to operands of type 'IntVector2' and
'IntVector2'
For context I am using this as a learning experience. I can get away without it (using intVectA.x == intVectB.x && intVectA.y == intVectB.y), but if I just go around the issue I will never learn why this is an error.
Also, my struct compiles completely without any errors.
You're trying to compare an IntVector2 to another IntVector2, but your implementations of the == and != operators take an IntVector2 and a Vector2. I don't see any other mention of a class or struct called Vector2 in your question. Is that a typo? The operators work fine for me if I change them to:
public static bool operator ==(IntVector2 a, IntVector2 b) { ... }
public static bool operator !=(IntVector2 a, IntVector2 b) { ... }
I'm introducing in C# Generic interfaces and clases, and there's a problem that I couldn't deal with, and I'll share the code here for if anyone could help me.
enum ListError
{
Ok = 0,
NoMemory,
ErrorPosition
}
interface IList<T>
{
int End();
ListError Insert<T>(T x, int p);
}
class ListArrays<T>: IList<T>
{
const int MAX = 100;
T [] data = new T[MAX];
int last = 0;
public int End()
{
return last+1;
}
ListError Insert<T>(T x, int p)
{
if (last >= MAX)
return ListError.NoMemory;
if (p > last || p < 0)
return ListError.ErrorPosition;
for (int q = last; q >= p; q--)
data[q] = data[q - 1];
last++;
data[p] = x;
return ListError.Ok;
}
}
I'm fighting with a compile time error in the line
data[p] = x;
which states:
Cannot implicitly convert type 'T [c:\Users\MartinD_PC\Documents\VisualStudio 2013\Projects\Aho_Hopcroft_Ullman\Aho_Hopcroft_Ullman\Chapter_2\ListaArreglos.cs(9)]' to 'T'
Change ListError Insert<T>(T x, int p) to ListError Insert(T x, int p). The compiler thinks you are specifying a new type T in Insert.
Note: Insert needs to be public (or explicit, since it's a interface implementation). Otherwise, that would be a another compilation error.
How could Reflection be used to determine the ways an object is cast from inside a method?
Example:
Given this type, which can be implicitly cast and assigned as an int, float, or string:
public class VersatileType {
public int intVal = 10;
public float floatVal = 1.5f;
public string stringVal = "words";
// implicit convertions
// ints
public static implicit operator int(VersatileType vt) {
return vt.intVal;
}
public static implicit operator VersatileType(int val) {
VersatileType vt = new VersatileType();
vt.intVal = val;
return vt;
}
// floats
public static implicit operator float(VersatileType vt) {
return vt.floatVal;
}
public static implicit operator VersatileType(float val) {
VersatileType vt = new VersatileType();
vt.floatVal = val;
return vt;
}
// strings
public static implicit operator string(VersatileType vt) {
return vt.stringVal;
}
public static implicit operator VersatileType(string val) {
VersatileType vt = new VersatileType();
vt.stringVal = val;
return vt;
}
}
And the given method which does some implicit casting and assigning:
public VersatileType obj;
public void CastAndAssignObj() {
obj = 0;
string text = obj;
}
Is there a way to use Reflection (or any other process) to determine how "obj" was cast/assigned from inside CastAndassignObj()?
I'd like to end up with a collection containing the Types int and string for the above example.
Many thanks-
Reflection will do you no good here because it will always produce VersatileType and that has 3 properties of type string, int and float reflection won't tell you which one is being used. I think the simplest way to do what you want is either to add a flag (isInt, isFloat, isString) or stop initializing those values so you can say
if (myVersatileType.StringVal != null)
// guess we're a string
You can't use reflection because it does not create different types. There is only one type, which has three values, and only one of those is used.
I came across a weird behavior when I changed an if-else to a ternary operator for a return statement.
I've simplified the code here:
class Foo
{
private bool condition;
private int intValue = 1;
private decimal decimalValue = 1M;
public object TernaryGet
{
get
{
return condition ? decimalValue : intValue;
}
}
public object IfElseGet
{
get
{
if (condition)
return decimalValue;
return intValue;
}
}
public Foo(bool condition)
{
this.condition = condition;
}
}
class Program
{
static void Main(string[] args)
{
var fooTrue = new Foo(true);
var fooFalse = new Foo(false);
Console.WriteLine("{0}, {1}", fooTrue.TernaryGet.GetType(), fooTrue.IfElseGet.GetType());
Console.WriteLine("{0}, {1}", fooFalse.TernaryGet.GetType(), fooFalse.IfElseGet.GetType());
}
}
The output from this is:
System.Decimal, System.Decimal
System.Decimal, System.Int32
I'd expect the second row to output Int32 on both getters, but for the ternary I'm getting the incorrect CLR type back for the int.
Never mind the code and what it's trying to do - I'm curious to why this is happening, so if anyone can explain it, I'd appreciate it.
Result of ternary (conditional) operator is always of single type - one/both of the options is casted to common type:
var result = condition ? decimalValue : intValue;
Type of result must be known statically at compile time. Since there is cast from int to decimal than decimal type is selected as type of whole ? : operator.
So you whole function can be written as (showing automatic casts):
public object TurnaryGet
{
get
{
/*decimal*/ var result = condition ? decimalValue : (decimal)intValue;
return (object)result;
}
}
condition ? decimalValue : intValue;
means
condition ? decimalValue : (decimal) intValue;
try if this work: (I'm stranger to C#, but this work in Java)
condition ? (object) decimalValue : (object) intValue;
It's likely that I'm just confused and wouldn't want to do this if I knew better, but here goes:
When you have int myInt = 5; you can access the value of that int just by calling the name of the variable: int myOtherInt = myInt + 1; or myInt ++;.
I have a struct that I want to behave this way, and return an existing value type.
In short, the struct has a Func field, and provides the result of that function; it also has Min/Max fields you use to clamp the output regardless of the raw result of the function.
Func<Foo, int> _func;
int _min;
int _max;
public MyStruct(Func<Foo, int> func, int min, int max) {...}
// Doesn't work
public int this
{
get { return Clamp(_min, _max, _func()); }
}
Clamp(min, max, val) {}
So, I want to be able to write:
var myStruct = new MyStruct((myFoo => myFoo.IntVal * 5), 1, 1000);
int myInt = myStruct + 5;
There are two options for you here. You can define an implicit casting operator, or you can define each of the arithmetic operators you're interested in.
Here's a full example of using the implicit cast operator. No this property needs to be implemented.
using System;
public struct MyStruct
{
public static implicit operator int(MyStruct myStruct)
{
return 2;
}
}
public class Test
{
public static void Main(string[] args)
{
var myStruct = new MyStruct();
var myInt = myStruct + 5;
Console.WriteLine("Int value: {0}", myInt);
}
}
In this case, myStruct + 5 implicitly casts your struct into an integer, using the overloaded operator you've implemented.
You should check out the Implicit operator:
http://msdn.microsoft.com/en-us/library/z5z9kes2(v=vs.71).aspx it has limitations, but could
get you a long way.
A nice post that does into examples and one of it's limitations:
http://www.markhneedham.com/blog/2009/02/22/c-implicit-operator/
You could do this by implementing public static implicit operator int(MyStruct astruct) (see http://msdn.microsoft.com/en-us/library/z5z9kes2(v=vs.71).aspx for more details.) and also an operator + (see http://msdn.microsoft.com/en-us/library/aa288467(v=vs.71).aspx for a tutorial).
public static MyStruct operator +(MyStruct astruct, int IntVal)
{
// code to add an int to the underlying value of your struct
}
public static implicit operator int(MyStruct astruct)
{
return return Clamp(_min, _max, _func());
}
with that, I think
int myInt = myStruct + 5;
should work, calling operator + for myStruct + 5 and then implicit operator int for the myInt = part.
Why not just overload the operator +(MyStruct a, int b)
A tutorial: http://msdn.microsoft.com/en-us/library/aa288467(v=vs.71).aspx