views:

1319

answers:

5

Is it possible to cast a custom class to a value type?

Here's an example:

var x = new Foo();
var y = (int) x; //Does not compile

Is it possible to make the above happen? Do I need to overload something in Foo ?

+9  A: 

You will have to overload the cast operator.

    public class Foo
    {
        public Foo( double d )
        {
            this.X = d;
        }

        public double X
        {
            get;
            private set;
        }


        public static implicit operator Foo( double d )
        {
            return new Foo (d);
        }

        public static explicit operator double( Foo f )
        {
            return f.X;
        }

    }
Frederik Gheysels
Can you please explain the use of implicit and explicit in your answer ? Thanks.
Andreas Grech
Plz see MSDN:http://msdn.microsoft.com/en-us/library/xhbhezf4(VS.80).aspxhttp://msdn.microsoft.com/en-us/library/z5z9kes2(VS.71).aspx(I would always prefer explicit cast operators)
Frederik Gheysels
Excellent, exactly what I was look for in the answer. Cheers.
Andreas Grech
+3  A: 

Create an explicit or implicit conversion:

public class Foo
{
 public static explicit operator int(Foo instance)
 {
  return 0;
 }

 public static implicit operator double(Foo instance)
 {
  return 0;
 }
}

The difference is, with explicit conversions you will have to do the type cast yourself:

int i = (int) new Foo();

and with implicit conversions, you can just "assign" things:

double d = new Foo();

MSDN has this to say:

"By eliminating unnecessary casts, implicit conversions can improve source code readability. However, because implicit conversions do not require programmers to explicitly cast from one type to the other, care must be taken to prevent unexpected results. 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. If a conversion operator cannot meet those criteria, it should be marked explicit." (Emphasis mine)

Rytmis
A: 

Another possibility is to write a Parse and TryParse extension method for your class.

You'd then write your code as follows:

var x = new Foo();
var y = int.Parse(x);
Mark
why would you write it as an extension method, and not as a regular member method ? It's his class, so he has control over it.
Frederik Gheysels
Because when you have a hammer every problem is a nail.
Martin Brown
@Mark: Even if you did write an extension method, you couldn't then use it with "var y = int.Parse(x);" because extension methods only apply to instances. You'd have to do something like "var y = x.ParseToInt();" instead, and in that case why not just put the ParseToInt method in the class itself, as Frederik says.
LukeH
Without knowing more about his Foo class I simply offered another possibility. @Martin Brown: Are you suggesting that the other Try and TryParse methods are hammers? No they fit their paradigm of dealing with strings. I can't really infer much of problem domain.@Frederik: He has just as much control with an extension method as he does with his own class.
Mark
No Mark, Martin is suggesting that extension methods are hammers. :)The problem with an extension method, is that you are scattering logic all over the place and, that the extension method will not be directly displayed by intellisense, if the namespace where the extension method is defined, is not 'used'.Since you have control over the foo class, it is better to write the TryParse method as a regular member method, instead of an extension method
Frederik Gheysels
@Mark: In England the Hammer thing is a saying that has perhaps a bit more meaning than the words convay. See http://en.wikipedia.org/wiki/Golden_hammer. I was trying to imply that people generally (not just you) on SO, have a habit of suggesting Extention methods and LINQ because they are the latest cool thing and not because they are the best tool for the job. In this case it is not the best tool because of all the reasons Frederik has just given.
Martin Brown
+4  A: 

You need to define explicit or implicit casting:

public class Foo
{
    public static implicit operator int(Foo d)
    {
        return d.SomeIntProperty;
    }

    // ...
arbiter
A: 

I would suggest you implement the IConvertible interface as that is designed to handle this. See http://msdn.microsoft.com/en-us/library/system.iconvertible.aspx

Ian