c# - 使用泛型和 'new' 修饰符隐藏父成员时的 C# 继承问题

标签 c# linq generics inheritance modifier

我正在尝试创建一个具有 2 个级别的类层次结构 其中第 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; }
}

这是一个演示问题的独立代码片段。

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;
        }
    }
}

有两个“测试者”类

  • 测试人员
  • TesterGeneric

Tester 使用具体类 Level2 并按 Id 属性对记录进行正确分组。

即输出:

  • 列表中的 6 个项目
  • 3 组唯一 ID

TesterGeneric 通过TEntity 通用参数引用 Level2 并且错误地Id 属性对记录进行分组。

即输出:

  • 列表中的 6 个项目
  • 仅1组(组Key为0)

问题: 这是怎么发生的?

最佳答案

我认为我们对 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();
    }


}

如果有帮助,请告诉我。

关于c# - 使用泛型和 'new' 修饰符隐藏父成员时的 C# 继承问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54228756/

相关文章:

c# - 需要左外连接类型时在 LINQ 中连接表的问题

c# - 索引 SQL 表会提高 LINQ 语句的性能吗?

java - 通用方法接受不同的数据类型列表

c# - 如何使用代码迁移配置禁用延迟加载,Entity Framework 4.1

c# - 返回两个值,这些值紧邻IEnumerable <float>中的测试值

c# - 如何防止访问本地文件系统

c# - 使用 Neo4jClient C# 按关系属性排序

LINQ 查询优化?

swift - 具有通用参数或 T 或 T 数组的 Swift 重载函数中的意外行为

java - 如何获取泛型类型 T 的类实例?