virtuality and user-defined conversions

W

Wayne

Are user-defined conversions chosen at compile time, or are there ways to
make sure that they are chosen at run-time, based on the actual type of the
object?

Here is a simplified example of what I'm trying to accomplish:

I have a method that has a parameter of type object. If the parameter is a
boxed uint, it should unbox it. So, the method looks like this:

void f(object o)
{
uint u = (uint)o;
}

I don't have access to this method's source code, and can't change it.

Now, I would like to pass it other types of objects besides boxed uints, and
have it convert them to uints. For example, I've created the following
class:

class WrappedUInt
{
private uint m_wrappedUInt;

public WrappedUInt(uint u)
{
m_wrappedUInt = u;
}

public static explicit operator uint(WrappedUInt w)
{
return w.m_wrappedUInt;
}
}

If I try the following, the conversion is not invoked and I get a class cast
exception:

WrappedUInt wu = new WrappedUInt(37);
f(wu);

However, if f() is modified as followed:

void f(WrappedUInt o)
{
uint u = (uint)o;
}

the conversion is invoked and everything works fine.

This seems to imply that conversion operators are only selected at compile
time based on static type information, and don't make use of runtime type
information. Is there any way I can define a conversion that's based on the
actual type of the object at run time, so that the first version of f() will
work?

Thanks for any help you can provide.

Wayne
 
N

Nicholas Paldino [.NET/C# MVP]

Wayne,

There isn't a way do to this in the way that you would like, that is, to
have the operator determined at runtime based on the actual type of the
instance.

What I don't get is why the signature isn't typed with a uint for the
parameter, unless you have a switch based on the type in the method itself.
If that's the case, then the best I think you can do is to create a wrapper
method which does some type checking beforehand and performs an appropriate
conversion based on whatever the most appropriate type is.

Hope this helps.
 
W

Wayne

Hi Nick --

Thanks for the info. I was afraid of that. The example was a
simplification, but I assume there's a switch statement in there. In any
case, it's a black box to me.

I thought about using a wrapper method, but it's not a practical solution
for a number of reasons that I can't go into. I'll need to take a different
approach to address this problem.

It's unfortunate that conversions don't depend on the actual runtime type --
it would essentially allow developers to define their own boxing and
unboxing operations.

Wayne

Nicholas Paldino said:
Wayne,

There isn't a way do to this in the way that you would like, that is,
to have the operator determined at runtime based on the actual type of the
instance.

What I don't get is why the signature isn't typed with a uint for the
parameter, unless you have a switch based on the type in the method
itself. If that's the case, then the best I think you can do is to create
a wrapper method which does some type checking beforehand and performs an
appropriate conversion based on whatever the most appropriate type is.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Wayne said:
Are user-defined conversions chosen at compile time, or are there ways to
make sure that they are chosen at run-time, based on the actual type of
the object?

Here is a simplified example of what I'm trying to accomplish:

I have a method that has a parameter of type object. If the parameter is
a boxed uint, it should unbox it. So, the method looks like this:

void f(object o)
{
uint u = (uint)o;
}

I don't have access to this method's source code, and can't change it.

Now, I would like to pass it other types of objects besides boxed uints,
and have it convert them to uints. For example, I've created the
following class:

class WrappedUInt
{
private uint m_wrappedUInt;

public WrappedUInt(uint u)
{
m_wrappedUInt = u;
}

public static explicit operator uint(WrappedUInt w)
{
return w.m_wrappedUInt;
}
}

If I try the following, the conversion is not invoked and I get a class
cast exception:

WrappedUInt wu = new WrappedUInt(37);
f(wu);

However, if f() is modified as followed:

void f(WrappedUInt o)
{
uint u = (uint)o;
}

the conversion is invoked and everything works fine.

This seems to imply that conversion operators are only selected at
compile time based on static type information, and don't make use of
runtime type information. Is there any way I can define a conversion
that's based on the actual type of the object at run time, so that the
first version of f() will work?

Thanks for any help you can provide.

Wayne
 
B

Ben Voigt

Wayne said:
Hi Nick --

Thanks for the info. I was afraid of that. The example was a
simplification, but I assume there's a switch statement in there. In any
case, it's a black box to me.

I thought about using a wrapper method, but it's not a practical solution
for a number of reasons that I can't go into. I'll need to take a
different approach to address this problem.

It's unfortunate that conversions don't depend on the actual runtime
type -- it would essentially allow developers to define their own boxing
and unboxing operations.

I'd suggest that you implement IConvertible<uint> instead of an implicit
operator uint.... however you're at the mercy of the black box
implementation and whether it allows for IConvertible.
Wayne

Nicholas Paldino said:
Wayne,

There isn't a way do to this in the way that you would like, that is,
to have the operator determined at runtime based on the actual type of
the instance.

What I don't get is why the signature isn't typed with a uint for the
parameter, unless you have a switch based on the type in the method
itself. If that's the case, then the best I think you can do is to create
a wrapper method which does some type checking beforehand and performs an
appropriate conversion based on whatever the most appropriate type is.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Wayne said:
Are user-defined conversions chosen at compile time, or are there ways
to make sure that they are chosen at run-time, based on the actual type
of the object?

Here is a simplified example of what I'm trying to accomplish:

I have a method that has a parameter of type object. If the parameter
is a boxed uint, it should unbox it. So, the method looks like this:

void f(object o)
{
uint u = (uint)o;
}

I don't have access to this method's source code, and can't change it.

Now, I would like to pass it other types of objects besides boxed uints,
and have it convert them to uints. For example, I've created the
following class:

class WrappedUInt
{
private uint m_wrappedUInt;

public WrappedUInt(uint u)
{
m_wrappedUInt = u;
}

public static explicit operator uint(WrappedUInt w)
{
return w.m_wrappedUInt;
}
}

If I try the following, the conversion is not invoked and I get a class
cast exception:

WrappedUInt wu = new WrappedUInt(37);
f(wu);

However, if f() is modified as followed:

void f(WrappedUInt o)
{
uint u = (uint)o;
}

the conversion is invoked and everything works fine.

This seems to imply that conversion operators are only selected at
compile time based on static type information, and don't make use of
runtime type information. Is there any way I can define a conversion
that's based on the actual type of the object at run time, so that the
first version of f() will work?

Thanks for any help you can provide.

Wayne
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top