Невозможно указать как класс ограничений, так и ограничение "class" или " struct
Я пытаюсь работать вокруг глумливый вопрос путем создания пользовательского макета IDbSet.
пользовательский макет:
public class DbSetMock : IDbSet<Tenant>
{
/* hidden all other implemented methods/properties */
public TDerivedEntity Create<TDerivedEntity>() where TDerivedEntity : class, Tenant
{
throw new NotImplementedException();
}
}
метод create дает ошибку сборки, которую я понятия не имею, как решить:
невозможно указать как класс ограничений, так и ограничение "class" или "struct"
удалить class
из ограничений приводит к другой ошибке сборки (которую я также не понимаю :( ).
ограничения для параметра типа "TDerivedEntity" тестов метода.ДАЛМАТИНЕЦ.Арендаторы.DbSetMock.Create () 'должен соответствовать ограничениям для параметра типа "TDerivedEntity" системы метода интерфейса.Данные.Сущность.IDbSet Create()'. Вместо этого рассмотрите возможность использования явной реализации интерфейса.
может ли кто-нибудь помочь мне успешно построить этот класс?
4 ответов
С TDerived
параметр типа ограничен Tenant
, добавив ограничения class
или struct
избыточна. Просто удалите class
ограничения.
обновление: Любопытно, что здесь существует конфликт между ошибками компилятора. Если вы "исправите" одно, вы получите другое, в бесконечном цикле отчаяния. К счастью, вторая ошибка, также дает нам выход: вы можете использовать явную реализацию интерфейса:
public class DbSetMock : IDbSet<Tenant>
{
TDerivedEntity IDbSet<Tenant>.Create<TDerivedEntity>()
{
throw new NotImplementedException();
}
}
там кажется чтобы не было способа реализовать этот метод без использование явной реализации интерфейса. Если вам это нужно как часть открытого интерфейса класса, я предлагаю создать другой метод, который реализация интерфейса пересылает в:
public class DbSetMock : IDbSet<Tenant>
{
TDerivedEntity IDbSet<Tenant>.Create<TDerivedEntity>()
{
return Create<TDerivedEntity>();
}
public TDerivedEntity Create<TDerivedEntity>() where TDerivedEntity : Tenant
{
throw new NotImplementedException();
}
}
Попробуйте удалить class
из метод, как это:
public class DbSetMock : IDbSet<Tenant>
{
/* hidden all other implemented methods/properties */
public TDerivedEntity Create<TDerivedEntity>() where TDerivedEntity : Tenant
{
throw new NotImplementedException();
}
}
class, Tenant
- это избыточный код.
в настоящее время в структуре есть только три наследуемых класса, потомки которых могут быть типами значений: Object
, ValueType
и Enum
. Все три этих типа являются типами классов, но любой тип, производный от ValueType
или Enum
будет тип значения, и любой тип, производный от Object
, который не является производным от ValueType
будет типом класса. С любым типом, отличным от вышеуказанного, a class
или struct
ограничение было бы избыточным или противоречивым; не случайно, C# запрещает ограничения, которые должны быть непосредственно указаны для вышеуказанных типов.
в некоторых языках и фреймворках преобладающая философия дизайна заключается в том, что если существует определенная форма выражения, в которой поведение, применимое к этой общей форме, было бы бесполезным, нет причин для дизайнера языка/фреймворка идти из пути, чтобы запретить такую форму. При такой философии было бы совершенно законно иметь общий тип, ограниченный запечатанным типом (например,Fnord)
. Такая вещь была бы бессмысленной, если бы тип, о котором идет речь, был запечатан и нет будущая версия будет когда-либо иначе, но поскольку применение нормальной интерпретации общих ограничений к такой ситуации дало бы разумное поведение, и поскольку могут возникнуть некоторые ситуации, в которых такие ограничения могут быть полезны (например, написание кода для использования класса, который находится в разработке и в настоящее время запечатан, но может быть или не быть запечатан в его окончательном выпуске или написание кода для интерфейс с кодом на основе отражения, который ожидает определенных универсальных форм), философия предполагает, что ограничение универсального типа запечатанным классом должно быть законным.
на некоторых других языках и фреймворках существует другая философия: если программист может ожидать, что какая-то конкретная форма конструкции предложит функции за пределами общей формы, но это не так, и если эта конкретная форма не будет казаться очень полезной без таких функций, язык должен запретить это, даже если конструкция будет иметь точное значение, которое было бы четко определено и не могло бы быть выражено другими средствами, если разработчики языка не видят причины для программистов хотеть выразить это фактическое значение.
тот факт, что ни C#, ни .net не имеют никаких проблем с ограничением одного параметра типа другим, даже если этот другой параметр имеет тип, который не будет принят в качестве ограничения, предполагает, что ограничение искусственно налагается язык обусловлен вышеупомянутой философией. К сожалению, ИМХО, поскольку есть много ситуаций, когда было бы полезно иметь возможность сказать, например
bool HasAnyFlags<T>(this T enum1, T enum2) where T:struct,System.Enum
и хотя .net с пользой разрешил бы такую конструкцию, и хотя единственное препятствие, которое мешает C# исключить его код, явно ищет такие ограничения, чтобы запретить их, разработчики C# решили запретить такие конструкции, а не позволить им вести себя так, как .net будет интерпретировать их (имеется в виду, что HasAnyFlags
не мог ничего сделать непосредственно с T
что это не могло сделать с System.Enum
и T
как System.Enum
обычно не быстрее, чем с помощью System.Enum
(иногда медленнее), но T
тем не менее может быть полезно по нескольким причинам:
- метод может обеспечить во время компиляции, что параметры должны быть перечисленным типом *same*
- метод может использовать статический класс ' EnumEvaluator` для генерации и статические делегаты кэша типа "Func", такие, что "HasAnyFlags(T enum1, T enum2)" могут быть реализованы как " возвращаемый EnumEvaluator.HasAnyFlags(enum1,enum2);`. Такая функция может быть более чем в десять раз быстрее, как перечисление.HasFlag`.
тем не менее, как бы полезно было указать такие ограничения, единственный способ указать их в C# - это указать исходный код C# на некоторый фиктивный тип, который может использоваться в качестве ограничения, а затем запустить скомпилированный код через утилиту, которая заменит все ссылки на фиктивный тип ссылками на тип, который нужно использовать в первую очередь.
Он говорит вам, что ограничений:
class, Tenant
избыточна. Вы можете просто удалить class
С Tenant
более ограничен, чем class
и включает в себя class
.