C# Casting with conversion operators - c#

I have a custom implementation of the string class. I added custom conversion operators between string and the class, and the casting is working normally. But, if I first cast the custom object to System.Object and then to string it says: "Unable to cast the type 'MyString' to type 'System.String'". Why is that? How can I enable it...
class MyString
{
public string S {get; set;}
public MyString(string s)
{
this.S = s;
}
public static implicit operator string(MyString s)
{
return s.S;
}
public static implicit operator MyString(string s)
{
return new MyString(s);
}
}
class Program
{
static void Main(string[] args)
{
MyString ms = new MyString("a");
string s = ms;
object o = ms;
string s1 = (string)o; // <-- this throws the exception!
}
}

Conversions like this have to be determined at compile-time - whereas in your final line, the compile-time type of o is just object, so the compiler doesn't "know" about your conversion as an option.
It's hard to know the best solution to your problem other than just saying "don't do that" - if you use dynamic instead of object (and you're using C# 4, of course) then it'll work - but personally I would just try not to rely on user-defined conversions like this. They make the codebase very hard to understand, IMO.
Anyone reading an expression (string) o where o is just object would expect it to be a simple cast, i.e. one which would fail if o didn't actually refer to a string (or was a null reference). Trying to find ways of confounding that expectation is a bad idea, IMO.

I'd override ToString in your class. And then use o.ToString() instead of (string)o.

Related

C# type cast from my type to my other type

My code gets an object with everything in it. And as per different needs, it needs to be cast to different individual type.
class A
{
public static explicit operator B (A value)
{
....
return new B();
}
}
class B
{
...
}
public static T Get<T>(...)
{
A a = new A();
return (T)A;
}
var b = Get<B>(...); // cannot convert a type of A to B
Any ideas?
You can't do this, as the compiler doesn't know (and there's no way to tell it) that there's a conversion from A to T. You'd need to constrain T in some way to indicate that, and you just can't do that - in the same way that you can't constrain T to have a + operator etc. (The C# team has been considering how what that might look like and how it might be implemented, but it's definitely not available at the moment.)
You need a way of telling the compiler how to convert from an A to a T - you could add a parameter to Get to tell it that:
public static T Get<T>(Func<A, T> converter)
{
A a = new A();
return converter(a);
}
You'd then call it with:
var b = Get<B>(a => (B) a);
for example.
C# doesn't support duck typing, but you could serialize your class A into a json string, then deserialize it into class B, any any properties that have the exact same names and types (or via a mapping you set up using JSON attributes or JSON settings) will make their way into class B as desired.

Dynamic Property Assignment Throws RuntimeBinderException

I am getting a RuntimeBinderException with the message
Cannot implicitly convert type 'object' to 'MyNamespace.SomeEnum?'. An explicit conversion exists (are you missing a cast?)
The following code generates that error:
public enum SomeEnum
{
Val1
}
public class Example
{
public SomeEnum? EnumMember { get; set; }
}
public static class Program
{
static void Main()
{
dynamic example = new Example();
// Works without issue
example.EnumMember = (dynamic)Enum.Parse(typeof(SomeEnum), "Val1");
// Works without issue
example.EnumMember = Enum.Parse(example.EnumMember.GetType(), "Val1");
// Throws the aforementioned RuntimeBinderException
example.EnumMember = Enum.Parse(typeof(SomeEnum), "Val1");
}
}
Why do to first two lines work (both return type dynamic), but the third throws an exception (when the return type is object)? I was under the impression that, when assigning to dynamic, the binding is performed using the actual, run-time type of the right-hand-side. Can someone please enlighten me as to why the third line is unable to run as written?
The compile-time type of the expression on the RHS of the = operator for the first two lines is dynamic. In the first case that's because you've cast to dynamic, and in the second case it's because you're using a dynamic value in one of the arguments.
In the third case, the compile-time type of the expression is object. So you're trying to do the equivalent of:
object x = Enum.Parse(typeof(SomeEnum), "Val1");
example.EnumMember = x;
That doesn't work, because there's no implicit conversion from object to SomeEnum?, which is what the compiler is trying to find at execution time.
Note that the nullability part really isn't relevant here - nor is the fact that it's an enum. It's just that the assignment operator is being bound dynamically, but using the compile-time time of the RHS. Here's a similar but simpler example:
class Test
{
public int Foo { get; set; }
static void Main()
{
dynamic example = new Test();
example.Foo = 10; // Fine
object o = 10;
example.Foo = o; // Bang
}
}
If you want the compiler to handle the assignment dynamically using the actual type of the value returned rather than the compile-time type, then using dynamic is exactly what you want to do - either cast to dynamic, or use:
dynamic value = ...;
target.SomeProperty = value;
You still need to do an implicit conversion for the third line
example.EnumMember = (SomeEnum) Enum.Parse(typeof(SomeEnum), "Val1");
EDIT
The reason that you still need implicit conversion is because Enum.Parse returns an object. Refer to the documentation below.
https://msdn.microsoft.com/en-us/library/essfb559(v=vs.110).aspx

Convert the user defined type to string and string to user defined type

Why .NET does not provide implicit or explicit conversion converting from string to the defined type and from the defined type to the string?
Example:
public class MyClass
{
public int Id;
public MyClass()
{
}
}
I can do:
var myClass = new MyClass() {Id=1};
string myClassString = myClass.ToString();
WHY I CANNOT DO?:
var myClassConverted = (MyClass) myClassString ;
Is there any serialization pattern exist can to that?
.ToString() is just a method , it can return any String value, this does not convert a class to a String.
We already have some questions about converting class to text:
Create an instance of a class from a string
C# Convert dynamic string to existing Class
Convert class to string to send via email
Converting Class to XML to string
Personally I use more the XML serialization approach, is very easy to serialize and deserialize and works very well with external services, like REST or SOAP.
ToString() is a method defined on the Object class which returns a new string instance and is not a type conversion.
There is no conversion that can be used to cast a String to your class but you can define your own custom conversion operator.
public class MyClass
{
public int Id;
public MyClass()
{
}
public static explicit operator MyClass(string s)
{
MyClass temp = new MyClass() { Id = Int32.Parse(s) };
// you should handle exceptions when string is not convertible to int
return temp;
}
}
You can then use your conversion:
MyClass c = (MyClass)("1");
From MSDN:
C# enables programmers to declare conversions on classes or structs so that classes or structs can be converted to and/or from other classes or structs, or basic types. Conversions are defined like operators and are named for the type to which they convert. Either the type of the argument to be converted, or the type of the result of the conversion, but not both, must be the containing type.
Conversion operators have the following properties:
Conversions declared as implicit occur automatically when it is required.
Conversions declared as explicit require a cast to be called.
All conversions must be declared as static.
You can find more on MSDN.
Quote from msdn Object.ToString Method :
The default implementation of the ToString method returns the fully qualified name of the type of the Object, as the following example shows.
using System;
public class Example
{
public static void Main()
{
Object obj = new Object();
Console.WriteLine(obj.ToString());
}
}
// The example displays the following output:
// System.Object
.ToString() does not contain any unique information of your current object so you can not reconstruct the object from this string.
If you want to serialize or deserialize your object take a look here:
How to save/restore serializable object to/from file?
You cant really compare ToString() with a "Explicit cast". Both are different indeed.
Plausible comparison should be like this. You should be trying to cast "MyClass to string", that would fail.
Neither Cast from MyClass to string nor string to MyClass` is allowed.*[1]
var myClass = new MyClass() {Id=1};
string myClassString = (string)myClass;//Note this also will fails since no conversion beween `MyClass` to `string`
When you compare ToString method ideally you should be comparing with FromString method unfortunately no such thing.
Back to your question
var myClassConverted = (MyClass)myClassString;
WHY I CANNOT DO?:
Because there is no implicit or explicit conversion between string to MyClass.
[1]To make it work you may use implicit or explicit operators though.

Default non indexer properties in C#

How can you create a default - non indexer - property in C#?
What I mean by this is I can see that I can create indexer default properties as illustrated on this MSDN page.
This allows me to do things like
Widgets widgets = new Widgets();
Widget result = widgets[1];
But what if I want to achieve something like what Nullable<T> does?
Where you can take
Nullable<decimal> nullDec = 1.23m;
decimal result = nullDec.Value;
OR
decimal result = (decimal)nullDec;
Which I assume is simply a default property implementation to nullDec.Value???
Nullable<T> has special handling in the compiler, but you can do most of that by adding implicit or explicit static conversion operators.
For example, for type Foo you can add an operator:
public static implicit operator string(Foo value)
{
return "abc";
}
public static implicit operator Foo(int value)
{
...
}
allowing:
Foo foo = ..
string s = foo; // uses string(Foo value)
and
int i = 123;
Foo foo = i; // uses Foo(int value)
If you inspect the code of Nullable{T} you will see that the explicit cast implementation is like this:
public static explicit operator T(Nullable<T> value)
{
return &value.Value;
}
So yes you are right.
The way Nullable<T> does it is by providing an explicit conversion operator to T.
So perhaps you are looking for something like:
public static explicit operator Widget(Widgets widgets)
{
// Argument checks here.
return widgets[0];
}
which would let you do:
Widgets widgets = ..
Widget firstWidget = (Widget)widgets;
This does look like a really dodgy and unintuitive API to me so I don't recommend doing this at all. Why not just stick to standard indexers?
Not very sure if I correct understant what you're asking for. Wouldn't be enough to implement cast operators on returning type to achieve what you want?
If it's not what you intend, please explain.
Such kind of features are compiler syntactic sugar (in IL code they all are converted to same low level code), so basically it won't be possible to do this without modifying the C# compiler source.

Is there a workaround for overloading the assignment operator in C#?

Unlike C++, in C# you can't overload the assignment operator.
I'm doing a custom Number class for arithmetic operations with very large numbers and I want it to have the look-and-feel of the built-in numerical types like int, decimal, etc. I've overloaded the arithmetic operators, but the assignment remains...
Here's an example:
Number a = new Number(55);
Number b = a; //I want to copy the value, not the reference
Is there a workaround for that issue?
you can use the 'implicit' keyword to create an overload for the assignment:
Suppose you have a type like Foo, that you feel is implicitly convertable from a string.
You would write the following static method in your Foo class:
public static implicit operator Foo(string normalString)
{
//write your code here to go from string to Foo and return the new Foo.
}
Having done that, you can then use the following in your code:
Foo x = "whatever";
It's still not at all clear to me that you really need this. Either:
Your Number type should be a struct (which is probable - numbers are the most common example of structs). Note that all the types you want your type to act like (int, decimal etc) are structs.
or:
Your Number type should be immutable, making every mutation operation return a new instance, in which case you don't need the data to be copied on assignment anyway. (In fact, your type should be immutable whether or not it's a struct. Mutable structs are evil, and a number certainly shouldn't be a mutable reference type.)
You won't be able to work around it having the C++ look, since a = b; has other semantics in C++ than in C#. In C#, a = b; makes a point to the same object like b. In C++, a = b changes the content of a. Both has their ups and downs. It's like you do
MyType * a = new MyType();
MyType * b = new MyType();
a = b; /* only exchange pointers. will not change any content */
In C++ (it will lose the reference to the first object, and create a memory leak. But let's ignore that here). You cannot overload the assign operator in C++ for that either.
The workaround is easy:
MyType a = new MyType();
MyType b = new MyType();
// instead of a = b
a.Assign(b);
Disclaimer: I'm not a C# developer
You could create a write-only-property like this. then do a.Self = b; above.
public MyType Self {
set {
/* copy content of value to this */
this.Assign(value);
}
}
Now, this is not good. Since it violates the principle-of-least-surprise (POLS). One wouldn't expect a to change if one does a.Self = b;
Instead of making a copy of the data when passing the reference you could make the class immutable. When the class is immutable having multiple references to it isn't a problem since it can't be changed.
Operations that changes the data would of course return new instances.
An earlier post suggested this:
public static implicit operator Foo(string normalString) { }
I tried this approach... but to make it work you need this:
public static implicit operator Foo(Foo original) { }
and the compiler won't let you have an implicit conversion function from your exact type, nor from any base type of yourself. That makes sense since it would be a backdoor way of overriding the assignment operator, which C# doesn't want to allow.
Here is a solution that worked for myself :
public class MyTestClass
{
private int a;
private string str;
public MyTestClass()
{
a = 0;
str = null;
}
public MyTestClass(int a, string str)
{
this.a = a;
this.str = str;
}
public MyTestClass Clone
{
get
{
return new MyTestClass(this.a, this.str);
}
}
}
Somewhere else in the code :
MyTestClass test1 = new MyTestClass(5, "Cat");
MyTestClass test2 = test1.Clone;
Maybe what you're looking for can be solved using C# accessors.
http://msdn.microsoft.com/en-us/library/aa287786(v=vs.71).aspx

Categories