2009-12-28 5 views
7

Je crée un opérateur de conversion explicite pour convertir une liste générique de types d'entités en une liste générique de types de modèles. Est-ce que quelqu'un sait pourquoi je reçois l'erreur suivante:erreur explicite de l'opérateur de conversion lors de la conversion de listes génériques

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

J'ai déjà un opérateur de conversion explicite entre Entity.objA et Model.objA qui fonctionne très bien. Le problème se pose lors de la tentative de conversion de la liste générique. Est-ce seulement possible?

Voici mon code:

public static explicit operator List<Model.objA>(List<Entity.objA> entities) 
    { 
     List<Model.objA> objs= new List<Model.objA>(); 
     foreach (Entity.objA entity in entities) 
     { 
      objs.Add((Model.objA)entity); 
     } 
     return claims; 
    } 

Merci pour toute aide.

Répondre

17

L'erreur "La conversion définie par l'utilisateur doit convertir vers ou à partir du type englobant" indique exactement ce que cela signifie. Si vous avez un opérateur de conversion

class MyClass { 
    public static explicit operator xxx(string s) { // details } 
    public static implicit operator string(xxx x) { // details } 
} 

Alors xxx doit être MyClass. C'est ce que l'on entend par "la conversion doit convertir vers ou à partir du type englobant". Le type englobant est MyClass.

La section pertinente de la spécification ECMA334 C# est 17.9.4:

A conversion operator converts from a source type, indicated by the parameter type of the conversion operator, to a target type, indicated by the return type of the conversion operator. A class or struct is permitted to declare a conversion from a source type S to a target type T only if all of the following are true, where S0 and T0 are the types that result from removing the trailing ? modifiers, if any, from S and T:

S0 and T0 are different types.

Either S0 or T0 is the class or struct type in which the operator declaration takes place.

Neither S0 nor T0 is an interface-type.

Excluding user-defined conversions, a conversion does not exist from S to T or from T to S.

Alors, voici votre code:

public static explicit operator List<Model.objA>(List<Entity.objA> entities) { 
    List<Model.objA> objs= new List<Model.objA>(); 
    foreach (Entity.objA entity in entities) { 
     objs.Add((Model.objA)entity); 
    } 
    return claims; 
} 

Le problème est que pour que cela soit défini comme un opérateur de conversion, il doit résider dans les classes List<Model.objA> ou List<Entity.objA> mais bien sûr vous ne pouvez pas le faire car vous n'avez pas accès à changer ces types. Vous pouvez utiliser Enumerable.Select pour projeter vers l'autre type, ou List<T>.ConvertAll. Par exemple:

public static class ListExtensions { 
    public static List<Model.objA> ConvertToModel(this List<Entity.objA> entities) { 
     return entities.ConvertAll(e => (Model.objA)e); 
    } 
} 
2

Fondamentalement, vous ne pouvez pas faire cela. Dans votre opérateur, le type d'entrée ou de sortie doit être du type qui déclare l'opérateur. Une option pourrait être une méthode d'extension, mais pour être honnête, LINQ Select se rapproche d'elle-même, tout comme List<T>.ConvertAll.

À titre d'exemple de l'approche de méthode d'extension:

public static class MyListUtils { 
    public static List<Model.objA> ToModel(this List<Entity.objA> entities) 
    { 
    return entities.ConvertAll(entity => (Model.objA)entity); 
    } 
} 

ou plus généralement avec LINQ Select:

public static class MyListUtils { 
    public static IEnumerable<Model.objA> ToModel(
    this IEnumerable<Entity.objA> entities) 
    { 
    return entities.Select(entity => (Model.objA)entity); 
    } 
} 

et il suffit d'utiliser someList.ToModel().

Questions connexes