C#泛型 - 如何返回特定类型?

Rap*_*Rap 12 c# generics inheritance

也许我说这一切都错了.

我有一堆派生自"Model"类的类,一个带有一堆常见属性和方法的基类.我希望他们都实现一组功能:

public abstract void Create();
public abstract T Read<T>(Guid ID);  //<--Focus on this one
public abstract void Update();
public abstract void Delete();
Run Code Online (Sandbox Code Playgroud)

然后我在像"约会"这样的子类中实现它,如下所示:

public override T Read<T>(Guid ID)
{
  var appt = db.Appointments.First(a => a.AppointmentID.Equals(ID));
  var appointment = new Appointment()
  {
    DateEnd = appt.dateEnd.GetValueOrDefault(),
    Location = appt.location,
    Summary = appt.summary
  };
return appointment;
}
Run Code Online (Sandbox Code Playgroud)

这会引发异常"无法将类型'约会'隐式转换为T".如果我将方法的签名更改为"public override Appointment Read(Guid ID)",那么编译器会说我没有在子类中实现抽象方法.

我错过了什么?谁能给我一些代码示例?

Gre*_*g D 19

看起来你可以使用通用基类!考虑以下内容:

class Model<T>
{
    public abstract T Read(Guid ID);
}

class Appointment : Model<Appointment>
{
    public override Appointment Read(Guid ID) { }
}
Run Code Online (Sandbox Code Playgroud)

现在你的子类都是强类型的.当然,权衡是你不再拥有一个基类.A Model<Appointment>和a不是一回事Model<Customer>.我一般都没有发现这是一个问题,因为它没有什么共同的功能 - 接口是相似的,但它们都使用不同的类型.

如果你想要一个共同的基础,你当然可以欺骗并实现一个object基于同样的常规任务的界面.例如,某种精神(未经测试,但想法在那里):

interface IModelEntity
{
    object Read(Guid ID);
}

class Model<T> : IModelEntity
{
    public T Read(Guid ID)
    {
        return this.OnRead(ID); // Call the abstract read implementation
    }

    object IModelEntity.Read(Guid ID)
    {
        return this.OnRead(ID); // Call the abstract read implementation
    }

    protected abstract virtual T OnRead(Guid ID);
}

class Appointment : Model<Appointment>
{
    protected override Appointment OnRead(Guid ID) { /* Do Read Stuff */ }
}
Run Code Online (Sandbox Code Playgroud)


Cha*_*ion 5

你需要装箱和投球。我想知道为什么这个方法是通用的?

return (T)(object)appointment;
Run Code Online (Sandbox Code Playgroud)


Cor*_*ton 5

这会有用吗?

public abstract T Read<T>(Guid ID) where T : IAppointment;
Run Code Online (Sandbox Code Playgroud)

  • 不,那不行.你在推理错误方向的约束; type参数约束约束*type参数*.假设有两个类,Appointment和Frob,它们都实现了IAppointment.阅读<Frob>将是合法的,因为Frob实现了IAppointment.但是你不能将Appointment类型的对象转换为Frob,因为它们都实现了IAppointment! (2认同)