有谁知道为什么C#不支持协变返回类型?即使在尝试使用接口时,编译器也会抱怨它是不允许的.请参阅以下示例.
class Order
{
private Guid? _id;
private String _productName;
private double _price;
protected Order(Guid? id, String productName, double price)
{
_id = id;
_productName = productName;
_price = price;
}
protected class Builder : IBuilder<Order>
{
public Guid? Id { get; set; }
public String ProductName { get; set; }
public double Price { get; set; }
public virtual Order Build()
{
if(Id == null || ProductName == null || Price == null)
throw new InvalidOperationException("Missing required data!");
return …Run Code Online (Sandbox Code Playgroud) 我们有一个抽象类BaseClass(注意泛型arg!)和一个名为me的方法.我回来了.
如果我们在具体类中使用Me,我们将得到一个返回类型对象.然后我们必须将Me的结果转换为我们最初使用的类型.
我们怎样才能实现Me返回它的实际类型?在这个例子中输入A?
public abstract class BaseClass<TIdentifier>{
public virtual object Me{ get { return this; } }
}
public class A: BaseClass<long>
{
}
public class B: BaseClass<long>
{
}
public class controller{
public void SomeMethod(){
var a = new A();
var b = new B();
var aObject = a.Me; // this will be of type object
var aObjectCasted = (A)aObject; // cast to original
// How I want it
var aConcrete = a.Me; // this returns type a
} …Run Code Online (Sandbox Code Playgroud) 我正在尝试理解协方差和LSP.从这个问题我可以看出C#不支持返回类型协方差.然而Liskov替换原则对返回类型强加协方差.
这是否意味着在C#中应用这个原则是不可能的?还是我想念一些东西?
c# liskov-substitution-principle covariance solid-principles
我有以下课程:
public class BaseContainer
{
public BaseItem item {get; set;}
}
public class ExtendedContainer : BaseContainer
{
new public ExtendedItem item {get; set;}
}
public class BaseItem{
public string Name { get; set; }
}
public class ExtendedItem : BaseItem
{
public string Surname { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
然后我有以下说明:
ExtendedItem ei = new ExtendedItem { Name = "MyName", Surname = "MySurname" };
ExtendedContainer ec = new ExtendedContainer { item = ei };
BaseContainer bc = ec;
string temp = …Run Code Online (Sandbox Code Playgroud) 我想要实现的简化示例如下所示:
public class Animal
{
public virtual Teeth teeth {get;set;}
}
public class Mouse : Animal
{
public override SmallTeeth teeth {get; set;} // SmallTeeth Inherits from Teeth
}
Run Code Online (Sandbox Code Playgroud)
这显然不起作用,因为牙齿必须与要在Mouse类中重写的Animal类中的类型相同.但是,在允许在从Animal继承的任何函数中使用更多派生类型的情况下,可以实现这样的事情吗?例如,如果Animal类包含一个咬合函数:
public void Bite()
{
teeth.bite()
Console.WriteLine("Ouch")
}
Run Code Online (Sandbox Code Playgroud)
我可以调用Bite()从Animal继承的函数,它将使用Mouse类的字段类型SmallTeeth.这可能吗?这是我做我想做的最好的方式吗?如果没有,这个问题的正确方法是什么?
我开始看到这种模式经常出现在我的代码中:
class Foo { }
interface IBar
{
Foo Foo { get; }
}
class Bar<TFoo> : IBar where TFoo : Foo
{
public TFoo Foo { get; private set; }
Foo IBar.Foo
{
get
{
return Foo;
}
}
}
Run Code Online (Sandbox Code Playgroud)
它的一些好处是:
if (something is IBar))的简单方法TFoo封闭构造的Bar<>s 中的强类型访问Foo接口中IBar的多态访问有人可能会争辩说,这种模式在框架中无处不在(例如List<T> : IList),但我想知道这是否只是 .NET 1.0 的残余,当泛型不存在时。
在我的脑海里,我主要担心的是,这IBar不一定是一个适当的合同,它定义了“酒吧”应该提供什么成员;访问通用类型的成员只是一种技巧。
此外,如果我开始为此目的添加接口,我很快就会难以维护并行继承层次结构。
我应该担心在我的代码库中传播这种模式吗?如果是这样,哪些替代模式可以提供上面列出的部分或全部 3 个好处?
因为不允许显式实现抽象成员,所以这个“理想”的解决方案是不可能的:
class Foo { …Run Code Online (Sandbox Code Playgroud) 本List<T>类实现了IEnumerable<T>接口.它有一个GetEnumerator返回a 的方法List<T>.Enumerator.
我有一个如下所示的类,它给出了一个编译错误,指出返回类型GetEnumerator与接口不匹配.
public class InsertionSortedSet<T> : IEnumerable<T>
{
public struct Enumerator : IEnumerator<T>
{
// Required interface implemented
}
// Other interface methods implemented
public Enumerator GetEnumerator()
{
return new Enumerator(this);
}
}
Run Code Online (Sandbox Code Playgroud)
'Entities.Helpers.InsertionSortedSet'未实现接口成员'System.Collections.Generic.IEnumerable.GetEnumerator()'.'Entities.Helpers.InsertionSortedSet.GetEnumerator()'无法实现'System.Collections.Generic.IEnumerable.GetEnumerator()',因为它没有匹配的返回类型'System.Collections.Generic.IEnumerator'.
鉴于它List<T>似乎返回它自己的Enumerator类(不是接口),但它确实实现了Enumeration<T>我很困惑的接口,因为我看不出我对那个类有什么不同.
List<T>有效?我想返回一个InsertionSortedSet<T>.Enumerator而不是界面,因为它避免拳击,我需要切出.
假设你有这个:
// General purpose
public interface ISerializer
{
IDataResult Serialize<T>(T instance);
}
// General purpose
public interface IDataResult
{
}
// Specific - and I implement IDataResult
public interface IMyCrazyDataResult : IDataResult
{
}
public class MyCrazySerializer : ISerializer
{
// COMPILE ERROR:
// error CS0738: 'MyCrazySerializer' does not implement interface member 'ISerializer.Serialize<T>(T)'.
// 'MyCrazySerializer.Serialize<T>(T)' cannot implement 'ISerializer.Serialize<T>(T)' because it does
// not have the matching return type of 'IDataResult'.
public IMyCrazyDataResult Serialize<T>(T instance)
{
throw new NotImplementedException();
}
} …Run Code Online (Sandbox Code Playgroud) 可能重复:
C#是否支持返回类型协方差?
为什么我不能这样实现接口?
考虑以下:
public interface IAnimal {
}
public class Animal : IAnimal {
}
public interface ICage {
IAnimal SomeAnimal {get;}
}
public class Cage : ICage{
public Animal SomeAnimal { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我已经阅读了很多关于IEnumerable的协方差和逆变的东西,但我不知道如何让上面的代码工作.我收到错误"Cage没有实现接口成员IAnimal".既然它定义了动物,它比IAnimal更明确,似乎协方差应该照顾我.
我错过了什么?提前致谢.
如果我有一个返回某个集合的方法的接口,是否可以返回集合类型的实现?
例如:
public interface IVehicle
{
IEnumerable<Part> GetParts(int id);
}
public class Car : IVehicle
{
List<Part> GetParts(int id)
{
//return list of car parts
}
}
public class Train : IVehicle
{
IEnumerable<Part> GetParts(int id)
{
//return IEnumerable of train parts
}
}
Run Code Online (Sandbox Code Playgroud)
如果没有,为什么不呢?
至少对我而言,这是有道理的.
c# ×10
inheritance ×4
interface ×4
covariance ×3
generics ×3
oop ×2
.net ×1
collections ×1
enumerator ×1
ienumerable ×1