Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

user-defined conversion must convert to or from the enclosing type

Tags:

c#

.net

ERROR:

user-defined conversion must convert to or from the enclosing type in:

public static explicit operator E(M value)
{
    return value.Value;
}
public static implicit operator M(E value)
{
    return new M { Value = value };
}

Example:

BaseModel

public abstract class BaseModel<E, M>
    where E : class, new()
    where M : BaseModel<E, M>, new()
{
    public BaseModel()
    {
        this.Value = new E();

    }

    public static explicit operator E(M value)
    {
        return value.Value;
    }
    public static implicit operator M(E value)
    {
        return new M { Value = value };
    }

    public E Value { get; set; }

    public override string ToString()
    {
        return Value.ToString();
    }
}

Usage:

public class Usuario
{
    public int PK_USUARIO { get; set; } //IDENTITY(1,1) NOT NULL,
    public bool USUA_NR_ATIVO { get; set; } //bit NOT NULL,
}

Model:

    [DisplayName("Status")]
    [System.ComponentModel.Editor(typeof(bool), typeof(bool))]
    public bool Ativo
    {
        get { return Value.USUA_NR_ATIVO; }
        set { Value.USUA_NR_ATIVO = value; }
    }
like image 908
user2448091 Avatar asked Dec 27 '13 11:12

user2448091


1 Answers

I see what you are trying to do. Unfortunately .NET does not allow to define conversion operators in the base class. They only can convert to the exact type. Either the argument or the return type must exactly match the current class.

So the conversion operator has to be defined in the derived class M. Of course, this breaks the DRY principle, but I have no idea how to implement generic conversion operators. I think this is not possible at all because the generic conversion would apply to an infinite number of types in general.

In the first case you could probably live with

public static explicit operator E(BaseModel<E,M> value)
{ return value.Value;
}

But the inverse conversion will not work. This would imply the E could convert to any type derived from BaseModel<E,M>. This is probably not what you intended.

However, you would need to define only one of the operators in any derived class if you could live with the generic conversion above. At least this is less DRY.


Some further comment: You should also know that using where X : new() is quite slow as it invokes Activator.CreateInstance which itself uses reflection to call the constructor.

You could avoid this by using a constructor that takes an E argument and a cached compiled expression to invoke this constructor. This avoids the reflection call for every instance but the first one.

like image 158
Marcel Avatar answered Oct 16 '22 06:10

Marcel