Click here to Skip to main content
15,886,199 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
Hello Code Project gurus.

I had previously written a class that was a wrapper around the C# decimal type. This allowed me to add all kinds of custom functionality that I needed. I am now trying to make this wrapper class generic, but I am encountering a compiler error that I don't quite understand...

The super-simplified example of my code is below. The compiler error I get is on the last line of code:
Cannot implicitly convert type 'int' to 'ConsoleApplication1.testing.WrapperForFloat'. An explicit conversion exists (are you missing a cast?)<


What I don't understand is why, when
int y = testImplied
is encountered, the compiler knows that WrapperForFloat is inheriting the
implicit operator int(Wrapper<T> val)
from Wrapper and compiles the conversion, but it does not know that
testImplied = x
should use WrapperFloat's inherited
implicit operator Wrapper<T>(int val)

Any explanation would be greatly appreciated.

What I have tried:

C#
namespace ConsoleApplication1
{
    using System;

    namespace testing
    {
        public class Wrapper<T>where T: IConvertible
        {
            private T _value;

            public Wrapper()
            {
                _value = default(T);
            }

            public Wrapper(T intialValue)
            {
                _value = intialValue;
            }

            public static implicit operator Wrapper<T>(int val)
            {
                var x = (T)Convert.ChangeType(val, typeof(T));
                return new Wrapper<T>(x);
            }

            public static implicit operator int(Wrapper<T> val)
            {
                return (int)Convert.ChangeType(val._value, typeof(int));
            }
        }

        public class WrapperForFloat : Wrapper<float>
        {
            public WrapperForFloat() : base() { }
            public WrapperForFloat(float initialval) : base(initialval) { }
        }

        class Program
        {
            static void Main(string[] args)
            {
                var testExplicit = new Wrapper<float>(10f);
                var testImplied = new WrapperForFloat(11f);

                int x = testExplicit;
                int y = testImplied;

                testExplicit = y;
                testImplied = x;
            }
        }
    }
}
Posted
Updated 26-Jul-18 0:26am
v4

It doesn't work because the return type is a Wrapper<t>, not a WrapperForFloat.

Essentially, you're doing this:
C#
WrapperForFloat wff = new Wrapper<float>(x);

That isn't going to work. The compiler won't do an implicit downcast from Wrapper<float> to WrapperForFloat for you.

[edit]
It doesn't work because the Wrapper class may not implement all of the methods exposed by the WrapperForFloat class, so you can't treat the resulting cast object as a real WrapperForFloat instance.
[/edit]


There isn't any nice way around this. See this discussion[^] and some possible work arounds.
 
Share this answer
 
v2
Comments
C Pottinger 1-Aug-18 12:03pm    
Thanks Dave. Sometimes you can't see the forest for all the trees.
testImplied = x 
should use WrapperFloat's inherited 
implicit operator Wrapper<T>(int val) 


Why would it? That operator converts from int to Wrapper<t>, you are asking for a conversion from int to WrapperForFloat. Even if that did work you can't upcast from Wrapper<t> to WrapperForFloat

Add this to WrapperForFloat

public static implicit operator WrapperForFloat(int val)
{
    return new WrapperForFloat(val);
}
 
Share this answer
 
Comments
C Pottinger 1-Aug-18 12:03pm    
Yup. Makes sense. Feeling silly now...

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900