I just noticed that you can do this in C#:
Unit myUnit = 5;
instead of having to do this:
Unit myUnit = new Unit(5);
Does anyone know how I can achieve this with my own structs? I had a look at the Unit struct with reflector and noticed the TypeConverter attribute was being used, but after I created a custom TypeConverter for my struct I still couldn't get the compiler to allow this convenient syntax.
You need to provide an implicit conversion operator from int to Unit, like so:
public struct Unit
{ // the conversion operator...
public static implicit operator Unit(int value)
{
return new Unit(value);
}
// the boring stuff...
private readonly int value;
public int Value { get { return value; } }
public Unit(int value) { this.value = value; }
}
You need to provide a cast operator for the class that takes an Int32.
Related
I have a class that pretends to be an int, so it has overloaded the various operators;
public class MyId
{
int value;
public virtual int Value
{
get { return this.value; }
set { this.value = value; }
}
public MyId(int value)
{
this.value = value;
}
public static implicit operator MyId(int rhs)
{
return new MyId(rhs);
}
public static implicit operator int(MyId rhs)
{
return rhs.Value;
}
}
However, when I use code like
PropertyInfo.SetValue(myObj, 13, null)
OR
MyId myId = 13;
int x = Convert.ToInt32(myId);
IConvertible iConvertible = x as IConvertible;
iConvertible.ToType(typeof(MyId), CultureInfo.CurrentCulture);
I get invalid cast. I'm puzzled, both calls seem to attempt to call convert on the int which will fail because int doesn't understand the type MyId (even though all the assignment operators are there). Any ideas of a workaround for this, I'm sure I must be missing something stupid?
Implicit conversions are a C# construct and are not available through reflection. Additionally, setting a field or property through reflection means that you must provide the appropriate type up front. You can attempt to circumvent this by using a custom TypeConverter (or some other means of custom conversion) to help convert your types at runtime prior to using reflection. Here's a rough example of a TypeConverter implementation.
public class MyIdTypeConverter : TypeConverter
{
public override object ConvertFrom(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture,
object value)
{
if (value is int)
return new MyId((int)value);
else if (value is MyId)
return value;
return base.ConvertFrom(context, culture, value);
}
}
Here's the type that we would be trying to set the Custom property on.
public class Container
{
[TypeConverter(typeof(MyIdTypeConverter))]
public MyId Custom { get; set; }
}
The code to call it would have to check the attribute and perform the conversion ahead of time, after which it could call SetValue.
var instance = new Container();
var type = typeof(Container);
var property = type.GetProperty("Custom");
var descriptor = TypeDescriptor.GetProperties(instance)["Custom"];
var converter = descriptor.Converter;
property.SetValue(instance, converter.ConvertFrom(15), null);
I read of a useful trick about how you can avoid using the wrong domain data in your code by creating a data type for each domain type you're using. By doing this the compiler will prevent you from accidentally mixing your types.
For example, defining these:
public struct Meter
{
public int Value;
public Meter(int value)
{
this.Value = value;
}
}
public struct Second
{
public int Value;
public Second(int value)
{
this.Value = value;
}
}
allows me to not mix up meters and seconds because they're separate data types. This is great and I can see how useful it can be. I'm aware you'd still need to define operator overloads to handle any kind of arithmetic with these types, but I'm leaving that out for simplicity.
The problem I'm having with this approach is that in order to use these types I need to use the full constructor every time, like this:
Meter distance = new Meter(5);
Is there any way in C# I can use the same mode of construction that a System.Int32 uses, like this:
Meter distance = 5;
I tried creating an implicit conversion but it seems this would need to be part of the Int32 type, not my custom types. I can't add an Extension Method to Int32 because it would need to be static, so is there any way to do this?
You can specify an implicit conversion directly in the structs themselves.
public struct Meter
{
public int Value;
public Meter(int value)
{
this.Value = value;
}
public static implicit operator Meter(int a)
{
return new Meter(a);
}
}
public struct Second
{
public int Value;
public Second(int value)
{
this.Value = value;
}
public static implicit operator Second(int a)
{
return new Second(a);
}
}
I have a class that pretends to be an int, so it has overloaded the various operators;
public class MyId
{
int value;
public virtual int Value
{
get { return this.value; }
set { this.value = value; }
}
public MyId(int value)
{
this.value = value;
}
public static implicit operator MyId(int rhs)
{
return new MyId(rhs);
}
public static implicit operator int(MyId rhs)
{
return rhs.Value;
}
}
However, when I use code like
PropertyInfo.SetValue(myObj, 13, null)
OR
MyId myId = 13;
int x = Convert.ToInt32(myId);
IConvertible iConvertible = x as IConvertible;
iConvertible.ToType(typeof(MyId), CultureInfo.CurrentCulture);
I get invalid cast. I'm puzzled, both calls seem to attempt to call convert on the int which will fail because int doesn't understand the type MyId (even though all the assignment operators are there). Any ideas of a workaround for this, I'm sure I must be missing something stupid?
Implicit conversions are a C# construct and are not available through reflection. Additionally, setting a field or property through reflection means that you must provide the appropriate type up front. You can attempt to circumvent this by using a custom TypeConverter (or some other means of custom conversion) to help convert your types at runtime prior to using reflection. Here's a rough example of a TypeConverter implementation.
public class MyIdTypeConverter : TypeConverter
{
public override object ConvertFrom(ITypeDescriptorContext context,
System.Globalization.CultureInfo culture,
object value)
{
if (value is int)
return new MyId((int)value);
else if (value is MyId)
return value;
return base.ConvertFrom(context, culture, value);
}
}
Here's the type that we would be trying to set the Custom property on.
public class Container
{
[TypeConverter(typeof(MyIdTypeConverter))]
public MyId Custom { get; set; }
}
The code to call it would have to check the attribute and perform the conversion ahead of time, after which it could call SetValue.
var instance = new Container();
var type = typeof(Container);
var property = type.GetProperty("Custom");
var descriptor = TypeDescriptor.GetProperties(instance)["Custom"];
var converter = descriptor.Converter;
property.SetValue(instance, converter.ConvertFrom(15), null);
Instead of writing
int i = new int();
i = 7;
One can write
int i = 7;
Is there a way I can get that style of initialisation for my own types?
MyType mt = xyz;
The closest you can come is by creating implicit conversions on your type. For example:
public class Unit
{
public static implicit operator Unit( string val )
{
return Unit.Parse( val );
}
public static Unit Parse( string unitString )
{
// parsing magic goes here
}
}
This would enable you to do something like this:
Unit width = "150px";
var width = Unit.Parse("150px"); // equivalent to previous line
Note that you cannot introduce new syntax; this would be impossible to implement:
Unit width = 150px;
since 150px does not represent a valid value type.
Note that implicit casting can get you into trouble in weird ways so don't over do it. Support implicit casting only to and from types that you're really going to need.
Alternatively, if you're using C# compiler 3.5 or up you can also use inline initialization which is more verbose but also more explicit:
Unit with = new { Value=150, UnitType=Units.Pixel };
For the specific example in your comment you could add an implicit conversion operator to the type.
Note that doing this is generally not recommended because it makes your code less readable. For example, something like String2 s2 = new String2("yo") is completely explicit about what is happening; not so with something like String2 s2 = "yo".
String2 s2 = "yo";
// ...
public sealed class String2
{
public readonly string _value;
public string Value { get { return _value; } }
public String2(string value)
{
_value = value;
}
public override string ToString()
{
return Value;
}
public static implicit operator String2(string value)
{
return new String2(value);
}
}
You can do it through implicit cast operators.
Here's an article that describes the concept:
http://www.codeproject.com/KB/cs/Csharp_implicit_operator.aspx
short answer is "no you can't". You're always going to hide a new somewhere.
In your specific case you could do some trick with implicit conversions like this:
class String2 {
private readonly string WrappedString;
public String2(string wrappedString) {
this.WrappedString = "my modified " + wrappedString ;
}
public override string ToString() {
return this.WrappedString;
}
// the "magic" is here: the string you assign to String2 gets implicitly
// converted to a String2
public static implicit operator String2(string wrappedString) {
return new String2(wrappedString);
}
}
that enables you to do:
String2 test = "test";
Console.WriteLine(test.ToString()); // writes: "my modified test" to the Console
but you get the "new" hidden in the implicit conversion anyway.
Another approach which may be more general and lands you not too far from the syntax you want is through extension methods:
static class StringExtensions {
public static String2 ToString2(this string that) {return new String2(that);}
}
with that in scope, you can do this:
var test2="anothertest".ToString2();
Apart from the questionable usefulness of this, I'd like to ask if it is possible to do something along these lines.
class MyPrimitive {
String value;
public String Value {
get { return value; }
set { this.value = value; }
}
}
// Instead of doing this...
MyPrimitive a = new MyPrimitive();
a.Value = "test";
String b = a.Value;
// Isn't there a way to do something like this?
MyPrimitive a = "test";
String b = a;
I like to wrap primitive types into custom classes using a property to make the get and set method perform other things, like validation.
Since I'm doing this quite often I thought that it'd be nice to also have a simpler syntax, like for the standard primitives.
Still, I suspect that this not only isn't feasible but could also be conceptually wrong.
Any insights would be most welcome, thanks.
Use a value type (struct) and give it an implicit conversion operator from the type you want on the right hand side of assignment.
struct MyPrimitive
{
private readonly string value;
public MyPrimitive(string value)
{
this.value = value;
}
public string Value { get { return value; } }
public static implicit operator MyPrimitive(string s)
{
return new MyPrimitive(s);
}
public static implicit operator string(MyPrimitive p)
{
return p.Value;
}
}
EDIT: Made the struct immutable because Marc Gravell is absolutely right.
You could use implicit casting. It's not recommended, but:
public static implicit operator string(MyString a) {
return a.Value;
}
public static implicit operator MyString(string a) {
return new MyString { value = a; }
}
Again, bad practice.