70 votes

Pourquoi trois propriétés dans DbParameterCollection sont-elles abstraites dans les assemblys de référence mais virtuelles sinon?

Je me déplace un projet à partir d' project.json pour le nouveau-style csproj format, et il comprend une classe dérivée de l' DbParameterCollection. Dans mon projet, je suis en utilisant le multi-ciblage, mais pour les fins de cette question, nous avons seulement besoin de se soucier net45.

Le compilateur me dit que je dois remplacer les trois propriétés que je n'avais pas avant:

Si vous suivez ces liens vers la documentation (qui sont pour .NET 4.5, vous verrez que toutes les propriétés sont virtuels - pas abstraite. Si je construis le code, tout en appelant csc, tout va bien... c'est seulement lors de l'utilisation de l' .NET SDK de Base que je tombe sur la question.

Voici un exemple de code pour reproduire le problème:

Dossier de projet:

<Project Sdk="Microsoft.NET.Sdk">    
  <PropertyGroup>
    <TargetFramework>net45</TargetFramework>
  </PropertyGroup>    
</Project>

Le code C#:

using System;
using System.Collections;
using System.Data.Common;

public class DummyParameterCollection : DbParameterCollection
{
    public override int Count => 0;
    public override object SyncRoot => null;
    public override void Remove(object value) {}
    public override void RemoveAt(int index) {}
    public override void RemoveAt(string parameterName) {}
    public override int Add(object value) => 0;
    public override void Insert(int index, object value) {}
    public override void AddRange(Array values) {}
    public override void Clear() {}
    public override bool Contains(object value) => false;
    public override bool Contains(string value) => false;
    public override void CopyTo(Array array, int index) {}
    public override int IndexOf(object value) => -1;
    public override int IndexOf(string parameterName) => -1;
    protected override DbParameter GetParameter(int index) => null;
    protected override DbParameter GetParameter(string parameterName) => null;
    protected override void SetParameter(int index, DbParameter value) {}
    protected override void SetParameter(string parameterName, DbParameter value) {}
    public override IEnumerator GetEnumerator() => null;
}

Erreurs:

DummyParameterCollection.cs(5,14): erreur CS0534: 'DummyParameterCollection" n'a pas hérité de mettre en œuvre abstraite membre 'DbParameterCollection.IsSynchronized.get' [c:\Users\skeet\Test\ParameterCollection\ParameterCollection.csproj]
DummyParameterCollection.cs(5,14): erreur CS0534: 'DummyParameterCollection" n'a pas hérité de mettre en œuvre abstraite membre 'DbParameterCollection.IsFixedSize.get' [c:\Users\skeet\Test\ParameterCollection\ParameterCollection.csproj]
DummyParameterCollection.cs(5,14): erreur CS0534: 'DummyParameterCollection" n'a pas hérité de mettre en œuvre abstraite membre 'DbParameterCollection.IsReadOnly.get' [c:\Users\skeet\Test\ParameterCollection\ParameterCollection.csproj]

Je crois que je connais la cause immédiate du problème, mais pas les raisons pourquoi c'est comme ça, ou la meilleure solution.

Il ressemble à l' .NET SDK de Base (et VS2017 quand il est chargé à ce projet) utilise la référence assemblées. Si j'ouvre l' C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Data.dll dans le Réflecteur, qui montre les propriétés comme étant abstraite ainsi. Alors que si j'ouvre l' c:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Data.dll, ce qui montre que les propriétés comme étant virtuel.

Je peux contourner ce problème en remplaçant les propriétés et le retour false de tous - mais est-ce la meilleure façon de gérer cette situation? Au-delà, est-il une bonne raison pour laquelle les assemblies de référence ne correspond pas à la vraie assemblées (et la documentation) dans ce cas? J'attendrais la référence assemblées générée automatiquement, donc c'est bizarre pour certaines choses pour être incorrecte comme ça...

23voto

natemcmaster Points 13402

La référence assemblages sont corrects. Dans .NET Framework 4.5, ces propriétés ont été abstract. Ils ont changé d' virtual dans .NET Framework 4.5.1. Il semble que vous avez découvert une documentation bug.

Comme vous avez probablement déjà deviné, la différence entre les deux System.Data.dll les assemblages que vous observez est en raison de comment .NET Framework sépare de référence assemblées et d'exécution des assemblages. L'ensemble de référence en C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Data.dll reflète fidèlement ce qui aurait été de 4,5 version d'exécution d' System.Data.dll. Si vous êtes en mesure d'obtenir une vieille machine qui n'a pas encore mis à niveau .NET Framework 4.5.1 (bonne chance), vous verrez que l'exécution de l'assemblée en C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Data.dll a ces propriétés, abstract. .NET Framework mises à niveau sur place. Sur une machine qui a mis à niveau .NET Framework 4.5.1 ou plus récent, C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Data.dll a été remplacé par la version mise à jour (avec virtual, pas abstract, propriétés).

Autant que des solutions de contournement: pour compiler net451 au lieu de cela, ou la mise en œuvre mannequin méthodes sont les meilleures approches. Vous pourriez faire d'autres trucs pour compiler contre une version différente de System.Data.dll mais je ne le recommande pas

Je ne pouvais pas trouver la documentation officielle sur les changements de l'API entre .NET Framework 4.5 4.5.1 ou une explication de pourquoi cela a changé, cependant, j'ai trouvé ce commentaire d'un membre de l'équipe d'Entity Framework: https://bugzilla.xamarin.com/show_bug.cgi?id=29167#c0.

La suite (insécable) des modifications ont été apportées au Système.Données de l'Api dans le .NET Framework 4.5.1 de la libération....

Les membres suivants ont été ajoutés.

  • Système.Les données.Commun.DbParameter.Précision
  • Système.Les données.Commun.DbParameter.L'échelle
  • Système.Les données.SqlClient.SqlConnectionStringBuilder.ConnectRetryCount
  • Système.Les données.SqlClient.SqlConnectionStringBuilder.ConnectRetryInterval

Les membres suivants ont été modifiés à partir de l'abstrait au virtuel.

  • Système.Les données.Commun.DbDataReader.Fermer
  • Système.Les données.Commun.DbDataReader.GetSchemaTable
  • Système.Les données.Commun.DbParameter.SourceVersion
  • Système.Les données.Commun.DbParameterCollection.IsFixedSize
  • Système.Les données.Commun.DbParameterCollection.IsReadOnly
  • Système.Les données.Commun.DbParameterCollection.IsSynchronized

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X