Assumptions
Let's assume we have a class like so...
public class SomeClass
{
public int Value { get; set; }
public static implicit operator SomeClass(int value)
{
return new SomeClass() { Value = value };
}
}
And then we're simply using an assignment, like so...
SomeClass mySpecialObj = 1; /* mySpecialObj.Value is now 1 */
Scenario
Now, if I assign a value to an object that already has a reference, e.g.
SomeClass mySpecialObj = 1; // 1st assignment
mySpecialObj = 2; // 2nd assignment
Question
On the 2nd assignment, is it possible to check the current value within the assignment operator?
public static implicit operator SomeClass(int value)
{
// can I check mySpecialObj.Value here??
}
You're not overloading the assignment operator, you're creating an implicit conversion from int to SomeClass. These are two very distinct things.
As such, mySpecialObj = 2 effectively means:
Create a new instance of SomeClass using the integer 2
And then assign that instance to the variable mySpecialObj
or,
mySpecialObj = new SomeClass{ Value = 2};
By now it should be clear that the answer is no, the conversion operation cannot know the value of the variable the new instance is going to be assigned to (if it is assigned to a variable).
You cannot do this in C#. The reason for this is that you are not overloading the assignment operator, you are defining an implicit conversion operator, which is not the same thing.
When you do this
mySpecialObj = 2;
C# creates a new, independent, object using the body of your conversion operator. By the time the reference is re-assigned, your code has already finished execution. Your code has no access to the variable being assigned, because that variable does not participate in the conversion defined by your operator. In fact, your operator can be used outside the context of an assignment - for example, if you do this
private static void Foo(SomeClass s) {
Console.WriteLine(s.Value);
}
the presence of the implicit conversion operator lets you do this:
Foo(123);
Now SomeClass produced from 123 is not assigned to any variable at all.
Related
If I have made a variable of a non-reference type, say int, nullable, i.e. int?, does this mean I need to use a constructor before assigning a value?
Normally to intialise a non-reference type variable I simply do
int foo = 5;
But if I have a nullable non-reference data type variable is initialisation neccessary, as below, or can I still use the simple initialisation above?
int? foo = new int();
foo = 5;
No. You don't need to create an instance before assignment. The int? is a struct which is created on assignment.
Your assignment foo = 5; is actually:
foo = new Nullable<int>(5);
This is all done by the compiler. No need to do this by yourself.
int? is a syntax sugar for Nullable<int>; as for Nullable<T> if we have look at its implementation
https://referencesource.microsoft.com/#mscorlib/system/nullable.cs,ffebe438fd9cbf0e
we'll find an implicit operator declaration:
public struct Nullable<T> where T : struct
{
...
[System.Runtime.Versioning.NonVersionable]
public static implicit operator Nullable<T>(T value) {
return new Nullable<T>(value);
}
...
}
So for any struct T instead of explicit constructor call
T value = ...
T? test = new Nullable<T>(value);
we can use implicit operator
T? test = value; // implicit operation in action
In your particular case T is int and we have
int? foo = 5;
I have a struct type in C#. I want to be able to convert null implicitly to this type. For instance, null could be represented by a special value of the struct type and the cast operator should return a struct with this value.
In C++, I could use an implicit cast operator overload of type std::nullptr_t. Is there a comparable type in C#?
I have had the idea to use a special NullType class which has no instances. This works but looks somehow ugly. Is there a better way?
Example:
class NullType
{
private NullType(){} // ensures that no instance will ever be created
}
struct X
{
private static readonly int nullValue = -1;
private int val;
public X(int val){ this.val= val; }
public static implicit operator X(NullType t)
{
return new X(nullValue);
}
}
class MainClass
{
public static void Main(string[] args)
{
X x = null; // Works now!
}
}
No, conversion operators only allow conversion from types, not from a specific value of a type, aka null, so there is no null conversion operator.
The best fitting operator without introducing own types would be this:
public static implicit operator X(object t)
But obviously you don't want to use this. It isn't very safe to use (t can be any value, and the only way to handle non-null cases in an exception).
That said, I think the way you've created it now, using a class that can't be initialized is the best way to do this. In fact the only question is: why do you want to use null, instead of 'just' an default value instance on your struct (X.Null).
A colleague developed a set of classes to manage various types of measurements so that the unit of measurement (deg F, deg C, or whatever) can be specified at run time. The classes have a ToString() method that returns a string containing the value and the unit, such as "100 C".
There is a class that has several members of these types. For the purpose of this question, let's work with CSimUnitTemperature. The class has implicit conversion operators for doubles:
// Type Casting
public static implicit operator double(SimUnitTemperature T) { return T.Temperature; }
public static implicit operator SimUnitTemperature(double temp)
{
SimUnitTemperature T = new SimUnitTemperature();
T.Temperature = temp;
return T;
}
The CSimRecipeSegment class has several members of type SimUnitTemperature. I can create a List object and use it as a data source for a DataGridView. But when I try to change a value shown as "100 C" to "110 C", I get a long exception message beginning with "Invalid cast from 'System.String' to 'SimShopMeasures.SimUnitTemperature'.
So, I tried to provide an implicit conversion from a string to a SimUnitTmeperature object, using a little string extension method I wrote that converts the first piece of a string into a double:
public static implicit operator string(SimUnitTemperature T)
{
return T.ToString();
}
public static implicit operator SimUnitTemperature(string tempString)
{
SimUnitTemperature T = new SimUnitTemperature();
T.Temperature = tempString.FirstValue();
return T;
}
But when I tried to use this, I got the same exception. Breakpoints on both of these methods were not hit when I tried to change a value in the DataGridView.
I know I can add public properties of type double to the class that is using all these temperatures, and that's probably what I'll do, but I think it would be cleaner to change the SimUnitTemperature class to let me do this.
Thank you very much.
What I really want to achieve: Introduce a global alias name for object.
As there are no global aliases in C# I want to workaround that by providing another class myclass to which all objects are implicitly convertable, e.g.:
myclass foo () { return new object(); } // should be ok
myclass bar () { return "bla"; } // should be ok
How to?
(a conversion operator:
public static implicit operator myclass(object o)
{
return new given();
}
just outputs compiler error cs0553)
Well, you can't do that. From section 10.10.3 of the C# 4 specification:
A class or struct is permitted to declare a conversion from a source type S to a target type T only if all of the following are true:
...
Exclusing user-defined conversions, a conversion does not exist from S to T or from T to S
That's not true in your case, hence the error.
You haven't said why you want to do this (you mention "no global aliases" but it's not clear what you're trying to achieve), but you just can't do this. You could create a constructor or a static method to create an instance of your class, but you can't do it with an operator.
I have (for example) an object of type A that I want to be able to cast to type B (similar to how you can cast an int to a float)
Data types A and B are my own.
Is it possible to define the rules by which this casting occurs?
Example
int a = 1;
float b = (float)a;
int c = (int)b;
Yes, this is possible using C# operator overloading. There are two versions explicit and implicit.
Here is a full example:
class Program
{
static void Main(string[] args)
{
A a1 = new A(1);
B b1 = a1;
B b2 = new B(1.1);
A a2 = (A)b2;
}
}
class A
{
public int Foo;
public A(int foo)
{
this.Foo = foo;
}
public static implicit operator B(A a)
{
return new B(a.Foo);
}
}
class B
{
public double Bar;
public B(double bar)
{
this.Bar = bar;
}
public static explicit operator A(B b)
{
return new A((int)b.Bar);
}
}
Type A can be cast implicitly to type B but type B must be cast explicitly to type A.
Assuming you want that to be an explcit operation you'll need to write an explicit cast operator like so:
public static explicit operator MyTypeOne(MyTypeTwo i)
{
// code to convert from MyTypeTwo to MyTypeOne
}
You can then use it like so:
MyTypeOne a = new MyTypeOne();
MyTypeTwo b = (MyTypeTwo)a;
I'd question whether you want to actually cast one type to another, or whether you actually want to convert instead. I'd say you should avoid writing cast operators for conversions, if you are just aiming to take advantage of a nice syntax :)
Also, in general it is advised not to use implicit casts, as they allow for unintended type converstions. From MSDN documentation on implicit:
However, because implicit conversions
can occur without the programmer's
specifying them, care must be taken to
prevent unpleasant surprises. In
general, implicit conversion operators
should never throw exceptions and
never lose information so that they
can be used safely without the
programmer's awareness.
You cant overload the cast operator in c# but you can use explicit and implicit conversion operators instead:
"Using Conversion Operators (C# Programming Guide)"