Generics and explicit / implicit operators

Consider the following scenario.

I have a method that returns ISomething, but maybe Somethingor Wrapped<Something>. So I used the result for Somethingto use it, but it fails, any help as to why and how to resolve it would be greatly appreciated.

class Program
{
    static void Main(string[] args)
    {
        var a = new DerivedSomething();
        var b = (DerivedSomething)new Wrapped<DerivedSomething>(a); //success
        var c = (DerivedSomething)_GetSomething(false); //success, obsiously!
        var d = (DerivedSomething)_GetSomething(true); //Unable to cast object of type 'test_bed.Wrapped`1[test_bed.DerivedSomething]' to type 'test_bed.DerivedSomething'.
        var e = (DerivedSomething)(ISomething)new Wrapped<DerivedSomething>(a);  //Unable to cast object of type 'test_bed.Wrapped`1[test_bed.DerivedSomething]' to type 'test_bed.DerivedSomething'.

        var works = ((DerivedSomething)_GetSomething(false)).DoSomethingElse(); 
        var fails = ((DerivedSomething)_GetSomething(true)).DoSomethingElse(); //cast exception
    }

    private static ISomething _GetSomething(bool wrap)
    {
        var something = new DerivedSomething();
        return wrap ? new Wrapped<DerivedSomething>(something) : (ISomething)something;
    }
}

public interface ISomething
{
    void DoSomething();
}

public abstract class Something : ISomething
{
    public void DoSomething()
    {
        //some code
    }
}

public class DerivedSomething : Something
{
    public void DoSomething()
    {
        //some code
    }

    public void DoSomethingElse()
    {
        //some code
    }
}

public class Wrapped<T> : ISomething
    where T : ISomething
{
    private readonly T _something;

    public Wrapped(T something)
    {
        _something = something;
    }

    public void DoSomething()
    {
        _something.DoSomething();
    }

    public static explicit operator T(Wrapped<T> wrapped)
    {
        return wrapped._something;
    }
}

It seems that if the type is displayed as an interface when trying to quit, then the operator was not found?

A โ€œsimpleโ€ solution would be to write a โ€œU-turnโ€ function, which, if desired, can expand Wrapped<Something>to Something, but I would prefer to use operators if possible.

Edit

I think the essence of the problem: outside _GetSomething()I donโ€™t know whether Somethingor will be returned Wrapped<Something>.

+3
3

, :

public static explicit operator T(Wrapped<T> wrapped)
{
        return wrapped._something;
}

,

var d = (Something)_GetSomething(true); //FAILS!

Something, Something - T:ISomething. , :

var d = (ISomething)_GetSomething(true); //SUCCESS!

, , :

public class Wrapped<T> : Something //Something and NOT ISomething 
    where T : ISomething
{
    .....
    .....
}
+2

( , ).

Try

var f = (Something)(Wrapped<Something>)_GetSomething(true);

, ISomething , ISomething Something, Something.

public class Wrapped<T> : ISomething public class Wrapped<T> : Something, , , Wrapped<T> T.

:
explicit operator - , , ( ISomething). , , . , .

+4
var d = (Something)(Wrapped<Something>)_GetSomething(true); 
var e = (Something)new Wrapped<Something>(a);
0
source

All Articles