2010-11-03 8 views
5

j'ai ce structPourquoi cette fonte-opération échoue

[Serializable] 
public struct Foo : IConvertible, IXmlSerializable, IComparable, IComparable<Foo> 
{ 
    private readonly int _value; 

    private Foo(int id) 
    { 
     this._value = id; 
    } 

    private IConvertible ConvertibleValue 
    { 
     get 
     { 
      return this._value; 
     } 
    } 

    public int CompareTo(object obj) 
    { 
     if (obj is Foo) 
     { 
      var foo = (Foo) obj; 
      return this.CompareTo(foo); 
     } 
     return -1; 
    } 

    public int CompareTo(Foo other) 
    { 
     return this._value.CompareTo(other._value); 
    } 

    public TypeCode GetTypeCode() 
    { 
     return this._value.GetTypeCode(); 
    } 

    bool IConvertible.ToBoolean(IFormatProvider provider) 
    { 
     return this.ConvertibleValue.ToBoolean(provider); 
    } 

    char IConvertible.ToChar(IFormatProvider provider) 
    { 
     return this.ConvertibleValue.ToChar(provider); 
    } 

    sbyte IConvertible.ToSByte(IFormatProvider provider) 
    { 
     return this.ConvertibleValue.ToSByte(provider); 
    } 

    byte IConvertible.ToByte(IFormatProvider provider) 
    { 
     return this.ConvertibleValue.ToByte(provider); 
    } 

    short IConvertible.ToInt16(IFormatProvider provider) 
    { 
     return this.ConvertibleValue.ToInt16(provider); 
    } 

    ushort IConvertible.ToUInt16(IFormatProvider provider) 
    { 
     return this.ConvertibleValue.ToUInt16(provider); 
    } 

    int IConvertible.ToInt32(IFormatProvider provider) 
    { 
     return this.ConvertibleValue.ToInt32(provider); 
    } 

    uint IConvertible.ToUInt32(IFormatProvider provider) 
    { 
     return this.ConvertibleValue.ToUInt32(provider); 
    } 

    long IConvertible.ToInt64(IFormatProvider provider) 
    { 
     return this.ConvertibleValue.ToInt64(provider); 
    } 

    ulong IConvertible.ToUInt64(IFormatProvider provider) 
    { 
     return this.ConvertibleValue.ToUInt64(provider); 
    } 

    float IConvertible.ToSingle(IFormatProvider provider) 
    { 
     return this.ConvertibleValue.ToSingle(provider); 
    } 

    double IConvertible.ToDouble(IFormatProvider provider) 
    { 
     return this.ConvertibleValue.ToDouble(provider); 
    } 

    decimal IConvertible.ToDecimal(IFormatProvider provider) 
    { 
     return this.ConvertibleValue.ToDecimal(provider); 
    } 

    DateTime IConvertible.ToDateTime(IFormatProvider provider) 
    { 
     return this.ConvertibleValue.ToDateTime(provider); 
    } 

    string IConvertible.ToString(IFormatProvider provider) 
    { 
     return this.ConvertibleValue.ToString(provider); 
    } 

    object IConvertible.ToType(Type conversionType, IFormatProvider provider) 
    { 
     return this.ConvertibleValue.ToType(conversionType, provider); 
    } 

    XmlSchema IXmlSerializable.GetSchema() 
    { 
     return null; 
    } 

    void IXmlSerializable.ReadXml(XmlReader reader) 
    { 
     var stringId = reader.ReadElementContentAsString(); 
     if (string.IsNullOrEmpty(stringId)) 
     { 
      return; 
     } 

     this = int.Parse(stringId); 
    } 

    void IXmlSerializable.WriteXml(XmlWriter writer) 
    { 
     writer.WriteValue(this); 
    } 

    public static implicit operator int(Foo value) 
    { 
     return value._value; 
    } 

    public static implicit operator Foo(int value) 
    { 
     Foo foo; 
     if (value > 0) 
     { 
      foo = new Foo(value); 
     } 
     else 
     { 
      foo = new Foo(); 
     } 
     return foo; 
    } 

    public override string ToString() 
    { 
     return this._value.ToString(); 
    } 
} 

maintenant je suis à défaut:

var intList = new List<int> 
{ 
    1, 
    2, 
    3, 
    4 
}; 
var fooList = intList.Cast<Foo>().ToList(); 

avec

System.InvalidCastException: spécifié n'est pas valide. à System.Linq.Enumerable.d__aa`1.MoveNext() à System.Collections.Generic.List`1..ctor (IEnumerable`1 collection) à System.Linq.Enumerable.ToList [TSource] (IEnumerable` 1 source) ...

+1

Voir [Pourquoi l'échec quand j'ai un casting implicite défini une opération Cast Linq ?] (Http://stackoverflow.com/questions/808725/why- fait-a-linq-castt-operation-fail-when-i-have-an-implicit-cast-defined) et ses threads liés. –

Répondre

10

la raison pour laquelle est que la fonction Cast est écrit contre les types génériques (c.-à-pas les types de béton). Il ressemble un peu à ce qui suit

public IEnumeralbe<T> Cast<T>(this IEnumerable source) { 
    foreach (object cur in source) { 
    yield return (T)cur; 
    } 
} 

L'opération coulé à l'intérieur de Cast ne peut se faire sur cette information générique qui ne comprend pas l'opérateur coulé specialzed sur Foo. Par conséquent ce code ne considère pas la conversion implicite ici et à la place essentiellement repose uniquement sur les conversions CLR.

Pour que cela fonctionne, vous devez effectuer directement le plâtre contre le type Foo. La meilleure façon de le faire est avec une sélection

var fooList = intList.Select(x => (Foo)x).ToList(); 
+0

alors comment puis-je obtenir ce travail? –

+0

@Andreas j'ai mis à jour la réponse pour inclure une solution – JaredPar

+0

:)) le ctor avec int-param est privé ... désolé mate ... aucune chance avec ça ... y at-il une autre solution au lieu de la '.Select () '? –

Questions connexes