在继承时覆盖具有相同参数但具有不同返回类型的方法

时间:2012-02-08 07:25:33

标签: c# asp.net inheritance override return-type

我发现了其他几个涉及这个主题的问题,但我似乎无法适应我的特殊情况。我觉得我已经偶然发现了答案但却没有意识到这一点。我只需要朝正确的方向轻推即可完成此任务。

我正在创建一个自定义ASP.NET RoleProvider。由于它继承自RoleProvider,我必须覆盖public string [] GetAllRoles()。但是,我发现string []不够用,所以我创建了一个名为ProjectRole的新类,并使GetAllRoles()返回List。

我的理由是我的自定义角色表包含​​的数据多于名称(如DescriptionE,DescriptionJ等多种语言中的ID,名称,描述等),我想返回有关角色的所有内容只是一个名字。

所以我们(为了简洁起见,缩短了)

public class ProjectRoleProvider : RoleProvider
{
    public override string[] GetAllRoles()
    {
        throw new NotImplementedException();
    }

    public override List<ProjectRole> GetAllRoles()
    {
        List<ProjectRole> rolelist = new List<ProjectRole>();

        SqlConnection conn = new SqlConnection(connstring);
        SqlCommand cmd = new SqlCommand("sprocGetAllRoles", conn);
        cmd.CommandType = CommandType.StoredProcedure;

        conn.Open();
        using (SqlDataReader reader = cmd.ExecuteReader())
        {
            if (reader.HasRows == true)
            {
                while (reader.Read())
                {
                    ProjectRole somerole = new ProjectRole();
                    somerole.ProjectRoleID = reader.GetGuid(reader.GetOrdinal("ProjectRoleID"));
                    somerole.RoleNameE = reader.GetString(reader.GetOrdinal("RoleNameE"));
                    somerole.RoleNameJ = reader.GetString(reader.GetOrdinal("RoleNameJ"));
                    somerole.DescriptionE = reader.GetString(reader.GetOrdinal("DescriptionE"));
                    somerole.DescriptionJ = reader.GetString(reader.GetOrdinal("DescriptionJ"));
                    rolelist.Add(somerole);
                }
            }
            reader.Close();
        }
        conn.Close();

        return rolelist;
    }

    public class ProjectRole
    {
       private Guid _projectRoleID = Guid.Empty;
       private string _roleNameE = String.Empty;
       private string _roleNameJ = String.Empty;
       private string _descriptionE = String.Empty;
       private string _descriptionJ = String.Empty;

       //public properties to interact with the private fields

       public ProjectRole()
       {
       }
    }
}

困扰我的事情是我可以将string [] GetAllRoles()单独保留为未实现,并将我的List GetAllRoles()命名为其他内容,如GetRoles(),然后一切都是精细。但是,当你打电话的时候真的不清楚,你看到Intellisense的两个选择(“我使用哪些?”)。是的,我可以使用XML注释并说,“嘿,不要使用它,而是使用GetRoles”,但我宁愿只是覆盖返回类型并完成它。

2 个答案:

答案 0 :(得分:4)

您提交的代码将无法编译,因为您尝试仅通过返回类型重载。这是无效的C#。 (正如试图“覆盖”未在基类中指定的方法签名。)

但不,一般情况下你不能这样做。实际上,如果你可能会很糟糕,因为继承点是一个只知道 base 类型的调用者应该能够编写:

string[] roles = provider.GetUserRoles();

如果他们不能这样做并取回合理的结果,那么你根本就没有履行RoleProvider的合同。

您可能首先派生自RoleProvider(如果您不希望您的课程用作 a {{1或者你应该以正常方式覆盖RoleProvider,并包含另一个具有不同名称的方法,的调用者知道你的具体子类(以及谁想要额外的信息)可以使用。

如果您尝试覆盖声明为返回一种类型的方法以提供更具体的但仍然兼容的返回类型,我会更加同情;它受Java支持,但不支持C#。对于接口,在这种情况下可以使用显式接口实现,但这个技巧不适用于抽象类。

答案 1 :(得分:2)

根本不可能更改覆盖的返回类型。

如果你写

会发生什么
string[] roles = ((RoleProvider)new ProjectRoleProvider()).GetAllRoles();

相反,您应该将覆盖标记为[Obsolete](请注意,这将生成编译器警告)。

但是,我建议您将版本重命名为GetRolesDetail(),以便更清楚地说明其差异。