views:

100

answers:

1

-Edit- Alternative question/example http://stackoverflow.com/questions/2486873/how-do-i-cast-a-to-object-to-class-b-when-a-can-typcast-to-b


I have class A, B, C. They all can implicitly convert to a string

public static implicit operator A(string sz_) {  ... return sz; }

I have code that does this

object AClassWhichImplicitlyConvertsToString

{
    ...
    ((IKnownType)(String)AClassWhichImplicitlyConvertsToString).KnownFunc()
}

The problem is, AClassWhichImplicitlyConvertsToString isnt a string even though it can be typecast into one implicitly. I get a bad cast exception. How do i say its ok as long as the class has an operator to convert into a string?

+7  A: 

There is almost certainly a better way of doing whatever it is you're trying to do. If you provide more context, you'll get more helpful answers.

If instead of (or as well as) making your classes implicitly covert to string you also give them a ToString override, you can then say:

((KnownType)AClassBlah.ToString()).KnownFunc()

However, you'll then get an exception on trying to cast a string into KnownType. So I have to ask: why are you trying to go via string in this situation? Casts are generally an ugly-ass thing that make you think "Maybe my design needs refactoring one day". They're not something you design into your class library as a recommended usage pattern. They're a low-level facility with predictable behaviour, so there is no way (and no good reason to provide a way) to override what an explicit cast does.

Update

Judging from your comment you are mixing together runtime polymorphism and static (compile time) conversion. They don't mix too well. Are you previously a user of dynamically typed languages? It seems like you might be. If you have a method:

void FiddleWithObject(object obj)
{
    // whatever
}

Then the author of that method has no compile-time knowledge of what operations are available on obj. So they can say:

void FiddleWithObject(object obj)
{
    if (obj is IFiddly)
    {
        // Cool
        obj.Fiddle();
    }
    else
        throw new Exception("Wrong type of object");
}

This then blows up at compile time for classes that aren't IFiddly. But in a statically typed language, you can say:

void FiddleWithObject(IFiddly obj)
{
    obj.Fiddle(); 
}

This will blow up at compile time if the wrong kind of object is passed, and you don't need to check anything at runtime. Less code, bugs found sooner... how neat is that?

The implicit conversion feature is part of the operator overloading set of features. These are all very much tied to static types. They are resolved at compile time based on the known type of the object. So if you don't know the actual class of an object, there is no (built-in) way to call operators on it. It just doesn't mix with dynamic typing.

If it is possible to get a string (such as a "name") from an IFiddly object, then you can make it a property on that interface:

public interface IFiddly
{
    void Fiddle();
    string Name { get; }
}

Or (as I noted before) you could just override ToString on any object, as that's a virtual method on the object class that all classes ultimately inherit from. So by saying:

var str = someObject.ToString();

You are going to be calling the ToString implementation defined in whatever class someObject is an instance of.

In summary:

  • virtual and abstract methods, and supported interfaces: these are for dynamic, runtime typing and polymorphism.
  • operator and implicit conversion overloading (and generics): these are for compile-time, static typing.
  • casts are disgusting.
Daniel Earwicker
Basically class A B C can be used for multiple things and implements multiple interfaces. A and B both implements IKnownType. I would like an exception to occur if i use C which doesnt implement it. Anyways in the same function i would like to call something generic that uses a string which all 3 supports. But they are classes like A and B so when i try to convert it to a string i get the bad exception or 'A' as in class A tostring, not the actual operator that class A has.
acidzombie24
[OT: Thanks for your comments on my answer, Daniel. I removed it because after some experimentation, I concluded I need to learn more about implicit conversions! :-) ]
T.J. Crowder
+1 for *"There is almost certainly a better way..."*
T.J. Crowder
Andreas Niedermair
Here is a better example http://stackoverflow.com/questions/2486873/how-do-i-cast-a-to-object-to-class-b-when-a-can-typcast-to-b also can you close this question?
acidzombie24
@acidzombie24 - that new question is *way* worse - you've made it *more* vague. See what you make of my new update before racing to close this question.
Daniel Earwicker
+1. So you are saying instead of typecasting it i should write a conversion function that takes obj as the input and outputs the type i want. Essentially use a function instead of a cast. That doesnt sound so bad. But, i want to make sure that is what you are saying. I'll think that unless you otherwise note it. I think i'll accept this answer.
acidzombie24
Effectively, yes. Explicit casting is not an overrideable operation in C#. If you want to be able to get a type A from some type B where the type is not known to be B at compile time, you need to name that operation (either as a property or method on the type B that returns a type A). You *could* cast it to B first and then try and use an implicit conversion to A on it. But if B is an interface, you can't add conversion operators on it. So it's much simpler just to provide meaningful names for such non-trivial operations.
Daniel Earwicker
Great AND informative answer!
acidzombie24
No problem, a pleasure.
Daniel Earwicker
interfaces are a great way to document and enforce API contracts. However, I'd avoid using `.ToString()` to represent a specific string conversion: it's unclear what the design-contract is there; and it's also accessible by accident by code that has no idea of the interface since it's specified not in the interface but in object.
Eamon Nerbonne
@Eamon - I agree. It's like a runtime polymorphic equivalent of the implicit conversion to string, and will usually be less clear than a specific named property. Besides which, if you can obtain one string from an object, there will probably be others (FirstName, LastName, etc).
Daniel Earwicker