C# creating an implicit conversion for generic class? - c#

I have a generics class that I used to write data to IsolatedStorage.
I can use an static implicit operator T() to convert from my Generic class to the Generic Parameter T
e.g.
MyClass<double> foo = new MyClass(187.0);
double t = foo;
My question is, how can I do the reverse?
MyClass<double> foo = new MyClass(187.0);
double t = 0.2d;
foo = t;
The implicit operator has to be static, so I'm not sure how I can pass in the instance of my class?

This class shows conversion between T and MyClass, both ways.
class MyClass<T>
{
public MyClass(T val)
{
Value = val;
}
public T Value { get; set; }
public static implicit operator MyClass<T>(T someValue)
{
return new MyClass<T>(someValue);
}
public static implicit operator T(MyClass<T> myClassInstance)
{
return myClassInstance.Value;
}
}

EDIT:
If you want to be able to change the value of T in your class, I would recommend exposing it as a property like:
T Value { get; set; }
That will allow you to change the value, instead of the behavior of the implicit operator returning an entirely new instance of the class.
You can and can't using implicit operators. Doing something like
public static implicit operator int(MyType m)
public static implicit operator MyType(int m)
will implicitly convert from MyType to int and from int to MyType respectively. However, you're right, since they are static, the int to MyType specifically will have to create a new instance of MyType and return that.
So this code:
MyClass<double> foo = new MyClass(187.0);
double t = 0.2d;
foo = t;
wouldn't replace the value in foo with t, the implicit operator would return an entirely new MyClass from t and assign that to Foo.

You should be able to convert the other way by simply specifying another implicit operator:
public static implicit operator MyClass<T>(T input)
{
return new MyClass<T>(input);
}

Related

C# Implicit operator with generic

I'm writing an abstract wrapper for enum in C # (I want something like enum in Vala). My code is:
public abstract class Wraper<T, TE>
where T : Wraper<T, TE>, new()
{
public TE Value;
public static implicit operator T(TE value)
{
return new T() { Value = value };
}
public static implicit operator TE(T value)
{
return value.Value;
}
}
I want to do with something like this:
public enum EFoo { A, B, C, D, E};
public class Foo : Wraper<Foo, EFoo>
{
public bool IsBla
{
get { return Value == EFoo.A || Value == EFoo.E; }
}
}
...
Foo foo = EFoo.A;
bool bla = foo.IsBla;
But the code does not compile because C # does not allow both generic parameter,. When compile reports an error:
User-defined conversion must convert to or from the enclosing type
On line
public static implicit operator T(TE value)
Is there any work around or in C# is not so simple?
The implicit operator must convert either from or to the class you are defining it in. Since you are trying to define it in the abstract base class, it can only convert from or to that class.
The line Foo foo = EFoo.A; does not work because you can't define that conversion in your abstract class, you can only define it in your Foo class.
If you changed your code, as I did below, to convert from/to the base class, the implicit conversions work but you don't get the result you want. Wraper<Foo,EFoo> foo2 = EFoo.A; works because it can be defined in the base class.
Your best bet is probably to use the initializer syntax when creating your foo Foo foo = new Foo { Value = EFoo.A }; or to create some generic conversion functions.
public abstract class Wraper<T, TE>
where T : Wraper<T, TE>, new()
{
public TE Value;
public static implicit operator TE(Wraper<T, TE> value)
{
return value.Value;
}
public static implicit operator Wraper<T, TE>(TE value)
{
return new T { Value = value };
}
}
public enum EFoo
{
A,
B,
C,
D,
E
}
public class Foo : Wraper<Foo, EFoo>
{
public bool IsBla
{
get
{
return Value == EFoo.A || Value == EFoo.E;
}
}
}

IEnumerable<T>.Cast won't work even if an explicit cast operator is defined?

I have an explicit conversion defined from type Bar to type Foo.
public class Bar
{
public static explicit operator Foo(Bar bar)
{
return new Foo(bar.Gar);
}
}
public class Foo
{
public string Gar { get; set; }
public Foo() { }
public Foo(string gar) { Gar = gar; }
}
However, when I do:
using System.Linq;
...
var manyFoos = manyBars.Cast<Foo>();
It throws an exception saying it can't cast.
How do I tell Cast to use my cast operator to try the conversion?
Cast operators are static methods that the compiler calls when you use casts in code. They cannot be used dynamically. Enumerable.Cast does a runtime cast of two unconstrained generic types, so it cannot know during compile time which cast operators to use. To do what you want, you can use Select:
manyFoos.Select(foo => (Bar)foo);
The linq Cast method essentially does a box and unbox. It is not aware of either implicit or explicit cast operators defined in C#, which the compiler treats standard method calls.
You'd have to do something like this:
var manyFoos = manyBars.Select(bar => (Foo)bar);
As all other answers pointed type is not known in compile time since Cast method is not generic. It holds type of object and makes a explicit cast to T. this fails because you don't have conversion operator from object to Foo. And that is not possible also.
Here is a work around using dynamics in which cast will be done in runtime.
public static class DynamicEnumerable
{
public static IEnumerable<T> DynamicCast<T>(this IEnumerable source)
{
foreach (dynamic current in source)
{
yield return (T)(current);
}
}
}
Then use it like
var result = bars.DynamicCast<Foo>();//this works
Use Select:
var manyFoos = manyBars.Select(bar => (Foo)bar);
Your code doesn't actually compile. I assume that there is a property "Gar" in the "Bar" class as well?
public class Bar
{
public string Gar { get; set; }
public static explicit operator Foo(Bar bar)
{
return new Foo(bar.Gar);
}
}
public class Foo
{
public string Gar { get; set; }
public Foo() { }
public Foo(string gar) { Gar = gar; }
}
static void Main(string[] args)
{
List<Bar> bars = new List<Bar>();
for (int i = 0; i < 10; i++)
bars.Add(new Bar() { Gar = i.ToString() });
var result = bars.Cast<Foo>();
}
+
I encaurage you to read about covariance.
Assuming A is convertible to B, X is covariant if X<A> is convertible to X<B>.
With C#’s notion of covariance (and contravariance), “convertible” means convertible via an implicit reference conversion— such as A subclassing B, or A implementing B. Numeric conversions, boxing conversions, and custom conversions are not included.
You have to do that with interfaces.

C# Explicit Operators and Inheritance

I'm sure this is a stupid question, but why does the following code not call the explicit operator for the cast on the child class MyBool?
public class DataType
{
public static explicit operator bool(DataType D)
{
return false;
}
public static explicit operator DataType(bool B)
{
return new DataType();
}
}
public class MyBool : DataType
{
public bool Value;
public MyBool()
{
Value = false;
}
public static explicit operator bool(MyBool B)
{
return B.Value;
}
public static explicit operator MyBool(bool B)
{
return new MyBool() { Value = B };
}
}
then:
List<DataType> Types = new List<DataType>();
Types.Add(new MyBool() { Value = true });
Types.Add(new MyBool() { Value = false });
foreach (DataType T in Types)
{
bool Value = (bool)T;
MessageBox.Show(Value.ToString());
}
Produces the output: false, false
Is my only option to write functions on each class to take the place of the explicit operator functions?
why does the following code not call the explicit operator for the cast on the child class MyBool?
Because the operator functions are static, hence also non-virtual and thus their target is resolved at compile time rather than runtime. This is the expected behaviour.
If you want to have polymorphic conversion operators you can call virtual functions inside the operators:
public abstract class DataType
{
public static explicit operator bool(DataType D)
{
return D.DoCastToBool();
}
public static explicit operator DataType(bool B)
{
// We haven’t got an instance of our class here.
// You can use a factory method pattern to emulate virtual constructors.
}
protected abstract bool DoCastToBool();
}
Operators are overloaded rather than overridden - in other words, the choice about which implementation to use is made at compile-time. The compiler only knows about T as DataType, so it calls the operator in DataType.
One option would be to remove the operator from MyBool, but add a virtual method in DataType, allowing for polymorphic behaviour:
public class DataType
{
public static explicit operator bool(DataType D)
{
// TODO: Decide how you want to handle null references
return D.ToBoolean();
}
protected virtual bool ToBoolean()
{
return false;
}
}
public class MyBool : DataType
{
// ...
protected override bool ToBoolean()
{
return Value;
}
}
Note that this won't work for the conversion from bool to a DataType, as in that case we don't have any information about which subtype of DataType you actually want to create.
(Side-note: your code would be easier to follow if you used the normal .NET naming conventions.)
Here's a garbage solution for you:
replace: bool Value = (bool)T;
with: bool Value = (bool)(T as MyBool);

Can I create accessors on structs to automatically convert to/from other datatypes?

is it possible to do something like the following:
struct test
{
this
{
get { /*do something*/ }
set { /*do something*/ }
}
}
so that if somebody tried to do this,
test tt = new test();
string asd = tt; // intercept this and then return something else
Conceptually, what you want to do here is in fact possible within .NET and C#, but you're barking up the wrong tree with regards to syntax. It seems like an implicit conversion operator would be the solution here,
Example:
struct Foo
{
public static implicit operator string(Foo value)
{
// Return string that represents the given instance.
}
public static implicit operator Foo(string value)
{
// Return instance of type Foo for given string value.
}
}
This allows you to assign and return strings (or any other type) to/from objects of your custom type (Foo here).
var foo = new Foo();
foo = "foobar";
var string = foo; // "foobar"
The two implicit conversion operators don't have to be symmetric of course, though it's usually advisable.
Note: There are also explicit conversion operators, but I think you're more after implicit operators.
You can define implicit and explicit conversion operators to and from your custom type.
public static implicit operator string(test value)
{
return "something else";
}
Expanding on MikeP's answer you want something like:
public static implicit operator Test( string value )
{
//custom conversion routine
}
or
public static explicit operator Test( string value )
{
//custom conversion routine
}

Implement math functions in custom C# type?

Could someone point me to the interface that I need to implement in order to get basic math operators (i.e. +, -, *, /) to function on a custom type?
You have to use operator overloading.
public struct YourClass
{
public int Value;
public static YourClass operator +(YourClass yc1, YourClass yc2)
{
return new YourClass() { Value = yc1.Value + yc2.Value };
}
}
public static T operator *(T a, T b)
{
// TODO
}
And so on for the other operators.
You can find a good example of operator overloading for custom types here.
public struct Complex
{
public int real;
public int imaginary;
public Complex(int real, int imaginary)
{
this.real = real;
this.imaginary = imaginary;
}
// Declare which operator to overload (+), the types
// that can be added (two Complex objects), and the
// return type (Complex):
public static Complex operator +(Complex c1, Complex c2)
{
return new Complex(c1.real + c2.real, c1.imaginary + c2.imaginary);
}
}
You need to overload the operators on the type.
// let user add matrices
public static CustomType operator +(CustomType mat1, CustomType mat2)
{
}
What you're looking for is not an interface, but Operator Overloading. Basically, you define a static method like so:
public static MyClass operator+(MyClass first, MyClass second)
{
// This is where you combine first and second into a meaningful value.
}
after which you can add MyClasses together:
MyClass first = new MyClass();
MyClass second = new MyClass();
MyClass result = first + second;
Here is the MSDN article on operators and overriding in C#: http://msdn.microsoft.com/en-us/library/s53ehcz3(loband).aspx

Categories