2010-11-03 8 views
5

Tengo esta estructura¿Por qué hace esto fundido operaciones de mecanismos

[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(); 
    } 
} 

ahora estoy en su defecto:

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

con

System.InvalidCastException: especificar la conversión no es válido. en System.Linq.Enumerable.d__aa`1.MoveNext() en System.Collections.Generic.List`1..ctor (colección IEnumerable`1) en System.Linq.Enumerable.ToList [TSource] (IEnumerable` 1 fuente) ...

+1

Ver [¿Por qué fracasa un moldeada operación LINQ cuando tengo una conversión implícita definida?] (Http://stackoverflow.com/questions/808725/why- does-a-linq-castt-operation-fail-when-i-have-an-implicit-cast-defined) y sus hilos enlazados. –

Respuesta

10

la razón es que la función Cast está escrito contra los tipos genéricos (es decir, no tipos de hormigón). Se parece un poco a la siguiente

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

La operación fundido en el interior de Cast sólo puede hacerse en esta información genérica que no incluye el operador de conversión specialzed en Foo. Por lo tanto, este código no considera la conversión implícita aquí y en su lugar esencialmente se basa únicamente en conversiones CLR.

Para que funcione, necesita que el reparto se realice directamente contra el tipo Foo. La mejor manera de hacerlo es con un selecto

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

entonces, ¿cómo puedo hacer que esto funcione? –

+0

@Andreas Actualicé la respuesta para incluir una solución – JaredPar

+0

:)) el ctor con int-param es privado ... lo siento amigo ... no hay posibilidad con eso ... ¿hay alguna otra solución en lugar del '.Select () ' –

Cuestiones relacionadas