首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在C#中调用虚方法的替代方法

在C#中调用虚方法的替代方法
EN

Stack Overflow用户
提问于 2013-02-20 22:24:33
回答 3查看 1.8K关注 0票数 6

我为我的C#对象使用了NHibernate,因此我有几个模型类。

让我们假设下面的例子:

代码语言:javascript
复制
using System;

namespace TestProject.Model
{
    public class Room
    {
        public virtual int Id { get; set; }
        public virtual string UniqueID { get; set; }
        public virtual int RoomID { get; set; }
        public virtual float Area { get; set; }

    }
}

到目前为止,用NHibernate映射这些对象工作得很好。现在,我想生成一个新的Room对象,并将其存储在数据库中。为了避免单独设置每个成员,我向模型类添加了一个新的构造函数。在下面的虚拟成员下面我写道:

代码语言:javascript
复制
public RoomProperty()
{

}


public RoomProperty(int pRoomId, int pArea)
{
        UniqueID = Guid.NewGuid().ToString();
        RoomID = pRoomId;
        Area = pArea;
}

使用FxCop分析我的代码会告诉我以下内容:

代码语言:javascript
复制
"ConstructorShouldNotCallVirtualMethodsRule"
This rule warns the developer if any virtual methods are called in the constructor of a non-sealed type. The problem is that if a derived class overrides the method then that method will be called before the derived constructor has had a chance to run. This makes the code quite fragile. 

This page也描述了为什么这是错误的,我也理解它。但是我不知道如何解决这个问题。

当我删除所有构造函数并添加以下方法时...

代码语言:javascript
复制
public void SetRoomPropertyData(int pRoomId, int pArea)
        {
            UniqueID = Guid.NewGuid().ToString();
            RoomID = pRoomId;
            Area = pArea;

        }

……为了在我调用标准构造函数之后设置数据,我不能启动我的应用程序,因为NHibernate初始化失败。上面写着:

代码语言:javascript
复制
NHibernate.InvalidProxyTypeException: The following types may not be used as proxies:
VITRIcadHelper.Model.RoomProperty: method SetRoomPropertyData should be 'public/protected virtual' or 'protected internal virtual'

但是当我在构造函数中设置虚拟成员时,将此方法设置为virtual将是相同的错误。如何避免这些错误(违规)?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-02-20 22:45:09

问题出在虚拟集上。将值传递给基类构造函数中的虚拟属性将使用重写集而不是基集。如果覆盖集依赖于派生类中的数据,那么你就有麻烦了,因为派生类的构造函数还没有完成。

如果你完全确定,任何子类都不会在覆盖集中使用其状态的任何数据,那么你可以在基类构造函数中初始化虚拟属性。考虑在文档中添加适当的警告。

如果可能,尝试为每个属性创建支持字段,并在基类构造器中使用它们。

也可以将属性初始化推迟到派生类。为此,在基类中创建一个初始化方法,您可以在派生类的构造函数中调用该方法。

票数 5
EN

Stack Overflow用户

发布于 2013-02-20 22:45:33

我希望以下其中一种方法能起作用:

  1. 使属性不是虚拟的(只要NHibernate支持它,就首选)。
  2. 从自动实现的属性更改为具有显式支持字段的属性,并在构造函数中设置字段,而不是将properties.
  3. Create设置为静态Create方法,该方法首先构造对象,然后在返回构造的对象之前设置属性的值。

编辑:我在评论中看到的选项#3中的不清楚。

代码语言:javascript
复制
public class Room
{
    public virtual int Id { get; set; }
    public virtual string UniqueID { get; set; }
    public virtual int RoomID { get; set; }
    public virtual float Area { get; set; }

    public static Room Create(int roomId, int area)
    {
        Room room = new Room();
        room.UniqueID = Guid.NewGuid().ToString();
        room.RoomID = roomId;
        room.Area = area;
        return room;
    }
}
票数 1
EN

Stack Overflow用户

发布于 2018-03-24 19:45:35

我的好主意是让基类-抽象和它的构造函数-保护。接下来,继承的类有它们的构造函数实例私有实例和-对于外部世界-统一的静态方法,如“”,它首先初始化构造函数,然后-以正确的顺序调用整个类方法集,最后-返回类的实例。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14982195

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档