10

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?

1
  • 1
    My question was "why does the following code not call the explicit operator...?" not "is this working properly?". Commented Jun 7, 2011 at 9:53

3 Answers 3

21

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();
}
Sign up to request clarification or add additional context in comments.

Comments

2

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.)

2 Comments

Jon, has this always been the case in .NET versions? Or has there been a time when .NET searched inheritance hierarchies? I ask because a bug related to this seems to coincide with a project upgrade to newer .NET. The object in question is typed as 'object' at compile time, but the run-time type does have the operator defined. I highly doubt this is the case but it has been suggested...
@Sprague: No, it's always been the case.
-1

Here's a garbage solution for you:

replace: bool Value = (bool)T;

with: bool Value = (bool)(T as MyBool);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.