Je viens de terminer le débogage d'un problème, où notre programme s'est écrasé sur un serveur de production, mais jamais sur les machines de développement.Le même code agit différemment sur différentes machines - quelle en serait la cause? (Problème de version de CLR?)
J'ai fait ce petit programme que je pouvais reproduire le problème avec:
using System;
using System.Collections.Generic;
using System.Linq;
namespace RunTimeBug
{
class Program
{
static void Main(string[] args)
{
var coll = new Collection {{"Test", new Data()}, {"Test2", new Data()}};
var dataSequence = coll.Cast<Data>().ToList();
Console.WriteLine(dataSequence.Count);
}
}
class Collection : Dictionary<string,Data>, IEnumerable<Data>
{
public new IEnumerator<Data> GetEnumerator()
{
foreach(var v in Values)
yield return v;
}
}
class Data { }
}
Lors de l'exécution sur ma machine, ce code imprime « 2 ». Lors de l'exécution sur le serveur de production, il échoue à l'exception suivante:
Unhandled Exception: System.InvalidCastException: Unable to cast object of type 'System.Collections.Generic.KeyValuePair
`2[System.String,RunTimeBug.Data]' to type 'RunTimeBug.Data'.
at System.Linq.Enumerable.<CastIterator>d__b0`1.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at RunTimeBug.Program.Main(String[] args)
La seule différence que je peux trouver sur ces machines, est que le Runtime CLR est une version 2.0.50727.4927 sur des machines, où il travaille, et la version 2.0.50727.1433 sur les machines où cela ne fonctionne pas. Pour autant que je sache, la méthode d'extension Cast obtient la mauvaise version de IEnumerable sur les anciennes machines, mais la "bonne" sur les nouvelles machines. Quelqu'un peut-il expliquer pourquoi je vois cela?
Qu'est-ce qui a changé entre les deux versions de CLR Runtime, qui pourrait en être la cause?
S'il vous plaît noter, j'ai déjà déployé un correctif, et je suis conscient que la classe Collection dans le code ci-dessus est de mauvaise conception, car il implémente 2 IEnumerable différents. Cela a été trouvé "dans la nature" dans notre produit, donc j'aimerais vraiment connaître la cause exacte.
Bref, si vous réimplémentez une interface, assurez-vous de réimplémenter tous les membres «liés». Dans le cas de 'IEnumerable', cela signifie implémenter 'IEnumerable .GetEnumerator()' et 'IEnumerable.GetEnumerator()'. –