简体   繁体   English

C#中的泛型和继承类型

[英]Generics and inherited types in C#

I'm a little confused about the best way to handle this particular situation. 我对处理这种特殊情况的最佳方法有些困惑。 I'm not 100% confident with using generics yet. 我对使用泛型还没有100%的信心。

I have a class, Model , and it has two derived types, 3DModel and 2DModel . 我有一个类Model ,它有两个派生类型3DModel2DModel

I have an abstract property in Model of class View , which also has two derived types, 3DView and 2DView . 我在View类的Model中有一个抽象属性,该属性还具有两个派生类型3DView2DView

When 3DModel calls the View property, I'd like 3DView returned, which I understand is where the generics come in (currently the 2D and 3D versions just have their own properties with the derived types). 3DModel调用View属性时,我希望返回3DView ,据我了解这是泛型的来源(当前2D和3D版本仅具有自己的派生类型属性)。

My problem is that to do this I think I need to change Model to Model<TView> and then provide a where in 3DModel and 2DModel . 我的问题是这样做,我想我需要将Model更改为Model<TView> ,然后在3DModel2DModel提供一个位置。 This requires changing every use of Model , 2DModel and 3DModel to accommodate this though, and it's used absolutely everywhere (including, as far as I can tell, making it impossible to convert instances of Model to either 3DModel or 2DModel ). 这需要改变对Model2DModel3DModel每次使用以适应这种情况,并且它绝对在所有地方都使用(据我所知,这包括将Model实例转换为3DModel2DModel )。

Am I right in thinking this is the only way to implement this? 我认为这是实现此目标的唯一方法吗? It seems like a lot of extra code for something so simple. 对于这么简单的事情,似乎有很多额外的代码。

Edit: 编辑:

Some example code 一些示例代码

public class View
{    
}

public class 3DView : View
{
}

public class Model
{
    public abstract View _view {get; set;}
}

public class 3DModel : Model
{
    public override 3DView _view {get; set;}
}

I get the Visual Studio error "Cannot change return type when overriding property". 我收到Visual Studio错误“覆盖属性时无法更改返回类型”。

You can keep your non-generic Model class, and introduce an abstract generic Model class. 您可以保留非泛型Model类,并引入抽象的泛型Model类。

public abstract class Model<TView> : Model where TView : View
{
    public new TView _view
    {
        get { return base._view as TView; }
        set { base._view = value; }
    }
}

public class View3D : View { }

public class Model3D : Model<View3D> { }

public class View2D : View { }

public class Model2D : Model<View2D> { }

The best solution for me is to use generic class, indeed. 实际上,对我来说最好的解决方案是使用通用类。

You have another solution (more ugly), is create an interface for your views, and define your method View() as following : 您还有另一个解决方案(更丑陋),它是为视图创建接口,并按如下所示定义方法View():

public IView View()

Then you can eventually create specific properties in your 2D/3D models : 然后,您最终可以在2D / 3D模型中创建特定的属性:

public 2DView 2DView()
{
    return this.View() as 2DView;
}

But you can't have the same result than with a generic class... 但是您不能获得与泛型类相同的结果...

There are two approaches here, I think. 我认为这里有两种方法。

First, you may use usual inheritance: 首先,您可以使用通常的继承:

public abstract class View 
{
    public abstract void Hello();
}

public class _3DView : View
{
    public override void Hello() 
    {
        Console.WriteLine("Hello from 3D View");
    }
}

public class _2DView : View
{
    public override void Hello() 
    {
        Console.WriteLine("Hello from 2D View");
    }
}

public abstract class Model
{
    public abstract View { get; }
}

public _3DModel : Model 
{
    public override View  { get { return new _3DView; } }
}

public _2DModel : Model 
{
    public override View  { get { return new _2DView; } }
}

Model model = new _3DModel();
model.View.Hello(); // have "Hello from 3D View"

Model anotherModel = new _2DModel();
anotherModel.View.Hello();  // have "Hello from 2D View"

This way you can work with models and views polymorphically and still can cast a View to, say, _3DView when needed. 这样,您可以多态使用模型和视图,并且仍可以在需要时将View _3DView

Or you can use generics like this: 或者您可以使用如下泛型:

// Views are declared the same way

public abstract class Model<TView>
    where TView: View
{
    public abstract TView View { get; }
}

public class _3DModel : Model<_3DView>
{
    public override _3DView View { get { return new _3DView; } }
}

public class _2DModel : Model<_2DView>
{
    public override _2DView View { get { return new _2DView; } }
}

Model<_3DView> model = new _3DModel();
model.View.Hello();

The downsize of generics approach is that you can't say something like this: 缩小泛型方法的范围是您不能这样说:

Model model = new _3DModel();

since there is no single model parent. 因为没有单个模型父代。 To my mind, generics approach makes no sense in this situation. 在我看来,在这种情况下,泛型方法毫无意义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM