Почему три свойства в DbParameterCollection абстрактные в ссылочных сборках, но виртуальные в противном случае?


я перемещаю проект из project.json в новый формат csproj, и он включает класс, производный от DbParameterCollection. В моем реальном проекте я использую мульти-таргетинг, но для целей этого вопроса нам нужно только заботиться о net45.

компилятор говорит мне, что я должен переопределить три свойства, которые мне не пришлось раньше:

если вы перейдете по этим ссылкам документации (которые предназначены для .NET 4.5), вы увидите, что все свойства виртуальный - не абстрактный. Если я создам код, просто позвонив csc, все хорошо... это только при использовании .Чистый базовый пакет SDK, что я бегу в проблему.

вот пример кода для воспроизвести проблему:

файл проекта:

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

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;
}

ошибки:

DummyParameterCollection.cs (5,14): ошибка CS0534: 'DummyParameterCollection' не реализует унаследованный абстрактный член 'DbParameterCollection.IsSynchronized.сделать' [c:UsersskeetTestParameterCollectionParameterCollection.csproj]
DummyParameterCollection.cs(5,14): ошибка CS0534: 'DummyParameterCollection' не делает реализовать унаследованный абстрактный элемент ' DbParameterCollection.IsFixedSize.сделать' [c:UsersskeetTestParameterCollectionParameterCollection.csproj]
DummyParameterCollection.cs (5,14): ошибка CS0534: 'DummyParameterCollection' не реализует унаследованный абстрактный член 'DbParameterCollection.IsReadOnly.сделать' [c:UsersskeetTestParameterCollectionParameterCollection.csproj]

я считаю, что знаю непосредственную причину проблемы, но не причины почему это как это, или лучшим решением.

похоже, что .NET Core SDK (и VS2017 при загрузке этого проекта) использует ссылочные сборки. Если я открою C:Program Files (x86)Reference AssembliesMicrosoftFramework.NETFrameworkv4.5System.Data.dll в рефлектор, это показывает свойства как абстрактные, а также. Тогда как если я открою c:WindowsMicrosoft.NETFrameworkv4.0.30319System.Data.dll, что показывает свойства, как виртуальную.

я могу обойти это, переопределив свойства и просто вернув false от всех них - но разве это лучший способ справиться с этой ситуацией? Кроме того, есть ли веская причина, по которой ссылочные сборки не соответствуют реальным сборкам (и документации) в этом случае? Я ожидал бы, что ссылочные сборки будут автоматически генерироваться, поэтому это странно для некоторые вещи, чтобы быть неправильным, как это...

1 62

1 ответ:

ссылочные сборки верны. В .NET Framework 4.5 эти свойства были abstract. Они были изменены на virtual в .NET Framework 4.5.1. Похоже, вы обнаружили ошибку в документации.

как вы, наверное, уже догадались, разница между двумя системами.Данные.сборки dll, которые вы наблюдаете, связаны с тем, как .NET Framework разделяет ссылочные сборки и сборки среды выполнения. Ссылочная сборка в C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Data.dll точно отражает то, что бы был в версии 4.5 времени выполнения System.Data.dll. Если вы можете получить старую машину, которая еще не обновлена до .NET Framework 4.5.1 (good luck), вы найдете эту сборку времени выполнения в C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Data.dll имеет эти свойства как abstract. Обновление .NET Framework на месте. На компьютере, обновленном до .NET Framework 4.5.1 или более поздней версии,C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Data.dll была заменена на обновленную версию (с virtual, а не abstract свойства.)

что касается обходных путей: компиляция для net451 вместо этого, или внедрение фиктивных методов является лучшим подходом. Вы можете сделать другие трюки для компиляции против другой версии системы.Данные.dll, но я бы не рекомендовал его

Я не смог найти официальную документацию по изменениям API между .NET Framework 4.5 и 4.5.1 или объяснение того, почему это было изменено, однако я нашел этот комментарий от члена команды Entity Framework:https://bugzilla.xamarin.com/show_bug.cgi?id=29167#c0.

в систему были внесены следующие (неразрушающие) изменения.API данных в выпуске .NET Framework 4.5.1....

были добавлены следующие элементы.