使用泛型和“新”修饰符隐藏父级成员时出现 C# 继承问题
Posted
技术标签:
【中文标题】使用泛型和“新”修饰符隐藏父级成员时出现 C# 继承问题【英文标题】:Issue with C# inheritance when using Generics and 'new' modifier to hide a parent's member 【发布时间】:2019-01-17 03:50:28 【问题描述】:我正在尝试创建具有 2 个级别的类层次结构 其中第二级覆盖其中一个属性(例如 Id)。
// Level 1
public class Level1 : IEntity
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id get; set;
// Level 2
public class Level2 : Level1
// Override the 'Id' property in Level1
// for the purpose of turning off auto-increment on Id.
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public new int Id get; set;
这是一个演示问题的自包含代码 sn-p。
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using Example;
public class Program
public static void Main()
// Using concrete class, logic works correctly
var tester = new Tester();
Console.WriteLine("\n");
// Using Generic, result is incorrect
var testerGeneric = new TesterGeneric<Level2>();
///////////////////////////////////////////////////////////////////////////
public class Tester
public Tester()
Console.WriteLine("------ Tester Class ------");
var listOfEntities = Level2.CreateDummyRecords();
Console.WriteLine("List Count = " + listOfEntities.Count()); // Returns 6 (as expected)
var groupedItems = listOfEntities.GroupBy(g => g.Id);
Console.WriteLine("Grouped By Count = " + groupedItems.Count()); // Returns 3 (as expected)
public class TesterGeneric<TEntity>
where TEntity : class, IEntity, new()
public TesterGeneric()
Console.WriteLine("------ TesterGeneric Class ------");
var listOfEntities = (IEnumerable<TEntity>) Level2.CreateDummyRecords();
Console.WriteLine("List Count = " + listOfEntities.Count()); // Returns 6 (as expected)
var groupedItems = listOfEntities.GroupBy(g => g.Id);
Console.WriteLine("Grouped By Count = " + groupedItems.Count()); // Returns 1 (should be 3)
///////////////////////////////////////////////////////////////////////////
namespace Example
public interface IEntity
int Id get; set;
// Level 1
public class Level1 : IEntity
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id get; set;
// Level 2
public class Level2 : Level1
// Override the 'Id' property in Level1
// for the purpose of turning off auto-increment on Id.
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public new int Id get; set;
public static IEnumerable<Level2> CreateDummyRecords()
var theList = new List<Level2>();
theList.Add(new Level2() Id=1 );
theList.Add(new Level2() Id=2 );
theList.Add(new Level2() Id=2 );
theList.Add(new Level2() Id=3 );
theList.Add(new Level2() Id=3 );
theList.Add(new Level2() Id=3 );
return theList;
有两个“测试者”类
测试人员 TesterGenericTester 使用具体类 Level2 并按 Id 属性正确分组记录。
即输出:
列表中有 6 项 3 组唯一 IDTesterGeneric 通过 TEntity 泛型参数引用 Level2 并且不正确按 Id 属性对记录进行分组。
即输出:
列表中有 6 项 仅1组(组Key为0)问题: 这是怎么发生的?
【问题讨论】:
使用new
遮蔽方法、属性或字段的情况很少见。这是邪恶的,应该避免。
【参考方案1】:
我认为我们对 new 和 override 有非常简单的概念。在这里你可以很容易地理解:
每当您覆盖子类属性/方法时,如果您将子对象转换为父类,那么您将拥有子类的功能。
每当您将 new 关键字与子类属性/方法一起使用时,如果您将子对象转换为父类,那么您将拥有父类功能。
这是给你的简单代码示例:
class Parent
public virtual int ID get return 40;
class ChildWithNew: Parent
public new int ID get return 50;
class ChildWithOverride : Parent
public override int ID get return 60;
class Program
static void Main(string[] args)
Console.WriteLine("---Child with Override Kyword");
ChildWithOverride cildWithOverride = new ChildWithOverride();
Console.WriteLine(cildWithOverride.ID);
Console.WriteLine(((Parent)cildWithOverride).ID);
Console.WriteLine("---Child with New Kyword");
ChildWithNew childWithNew = new ChildWithNew();
Console.WriteLine(childWithNew.ID);
Console.WriteLine(((Parent)childWithNew).ID);
Console.ReadLine();
如果有帮助,请告诉我。
【讨论】:
谢谢@gaurav,它非常有用。问题解决了。我现在知道 Override 和 New 之间的区别了。【参考方案2】:您没有覆盖属性 ID,现在您只是隐藏了您的属性。一旦您在 ID 中提供 virtual 和覆盖,问题就会得到解决。
【讨论】:
以上是关于使用泛型和“新”修饰符隐藏父级成员时出现 C# 继承问题的主要内容,如果未能解决你的问题,请参考以下文章