首页 > 解决方案 > 访问列表通过指定派生类

问题描述

我有一个抽象的 Player 类,其中包含派生的 HockeyPlayer、BasketballPlayer 和 BaseballPlayer。

public abstract class Player
    {
        enum PlayerType
        {
            HockeyPlayer,
            BasketballPlayer,
            BaseballPlayer
        }

        public abstract void Points();
        private int playerId;
        private string playerName;
        private string teamName;
        private int gamesPlayed;

        public int PlayerId
        {
            get { return playerId; }
            set { playerId = value; }
        }
        public string PlayerName
        {
            get { return playerName; }
            set { playerName = value; }
        }
        public string TeamName
        {
            get { return teamName; }
            set { teamName = value; }
        }
        public int GamesPlayed
        {
            get { return gamesPlayed; }
            set { gamesPlayed = value; }
        }
    }
    public class HockeyPlayer : Player
    {
        private int assists;
        private int goals;
        

        public override void Points()
        {
            int totalPoints = assists + (2 * goals);
        }
        public int Assists
        {
            get { return assists; }
            set { assists = value; }
        }
        public int Goals
        {
            get { return goals; }
            set { goals = value; }
        }

    }
    public class BasketballPlayer : Player
    {
        private int fieldGoals;
        private int threePointers;
        public override void Points()
        {
            int totalPoints = (fieldGoals - threePointers) + (2 * threePointers);
        }
        public int FieldGoals
        {
            get { return fieldGoals; }
            set { fieldGoals = value; }
        }
        public int ThreePointer
        {
            get { return threePointers; }
            set { threePointers = value; }
        }
    }
    public class BaseballPlayer : Player
    {
        private int runs;
        private int homeRuns;
        public override void Points()
        {
            int totalPoints = (runs - homeRuns) + (2 * homeRuns);
        }
        public int Runs
        {
            get { return runs; }
            set { runs = value; }
        }
        public int HomeRuns
        {
            get { return homeRuns; }
            set { homeRuns = value; }
        }
    }
}

接下来在我的控制器中,我创建了一个列表并添加了一些 HockeyPlayers、BasketbalPlayers、BaseballPlayers

class Controller
    {
        private static List<Player> players = new List<Player>();
        static void Main(string[] args)
        {
            
            players.Add(new HockeyPlayer() { PlayerId = 1, PlayerName = "Mitch marner", TeamName = "Toronto Maple Leafs", GamesPlayed = 5, Assists = 12, Goals = 7 });
            players.Add(new BasketballPlayer() { PlayerId = 2, PlayerName = "Kyle Lowry", TeamName = "Toronto Raptors", GamesPlayed = 15, FieldGoals = 12, ThreePointer = 7 });
            players.Add(new BaseballPlayer() { PlayerId = 3, PlayerName = "Jose Bautista", TeamName = "Toronto Blue Jays", GamesPlayed = 5, Runs = 12, HomeRuns = 7 });

稍后在控制器类中,我有一个仅用于显示 hockeyPlayers 的方法,因此 enum playerType == Player.HockeyPlayer

static void viewHockeyPlayer()
        {
            Console.WriteLine("View ALL hockey players");
            Console.WriteLine($"{"Player Id",-15} {"Player Name",-15} { "Team Name",-15} {"Games Played",5} {"Assists",5} {"Goals",5}\n");
            
            foreach (var hock in players)
            {
                Console.WriteLine($"{hock.PlayerId,-15} {hock.PlayerName,-15} { hock.TeamName,-15} { hock.GamesPlayed, 5}");
            }
        }

如您所见,我无法添加仅针对 HockeyPlayer 类的 {hock.Assists} 或 {hock.Goals}。同样到目前为止,我这个方法打印出所有的 PlayerTypes,我无法弄清楚如何只打印出一个特定的类型。访问列表时如何指定 PlayerType?

标签: c#.netlistlinqinheritance

解决方案


使用模式匹配https://docs.microsoft.com/en-us/dotnet/csharp/pattern-matching

foreach (HockeyPlayer hock in players.Where(x => x is HockeyPlayer))
{
    Console.WriteLine($"{hock.Assists}");
}

或者

foreach (var player in players)
{
    if (player is HockeyPlayer hockeyPlayer)
        Console.WriteLine($"{hockeyPlayer.Assists}");
}

我更喜欢第二变种。

所有代码(我对其进行了一点重构):

using System;
using System.Collections.Generic;

namespace Game
{
    enum PlayerType
    {
        HockeyPlayer,
        BasketballPlayer,
        BaseballPlayer
    }

    public abstract class Player
    {
        public abstract void Points();

        public int PlayerId { get; set; }

        public string PlayerName { get; set; }

        public string TeamName { get; set; }

        public int GamesPlayed { get; set; }
    }

    public class HockeyPlayer : Player
    {
        public override void Points()
        {
            int totalPoints = Assists + (2 * Goals);
        }

        public int Assists { get; set; }

        public int Goals { get; set; }
    }

    public class BasketballPlayer : Player
    {
        public override void Points()
        {
            int totalPoints = (FieldGoals - ThreePointers) + (2 * ThreePointers);
        }

        public int FieldGoals { get; set; }

        public int ThreePointers { get; set; }
    }

    public class BaseballPlayer : Player
    {
        public override void Points()
        {
            int totalPoints = (Runs - HomeRuns) + (2 * HomeRuns);
        }

        public int Runs { get; set; }

        public int HomeRuns { get; set; }
    }

    class Program
    {
        static void ViewHockeyPlayer()
        {
            Console.WriteLine("View ALL hockey players");
            Console.WriteLine($"{"Player Id",-15} {"Player Name",-15} { "Team Name",-15} {"Games Played",5} {"Assists",5} {"Goals",5}{Environment.NewLine}");

            foreach (var player in players)
            {
                if (player is HockeyPlayer hock)
                    Console.WriteLine($"{hock.PlayerId,-15} {hock.PlayerName,-15} {hock.TeamName,-15} {hock.GamesPlayed,5} {hock.Assists,5} {hock.Goals,5}");
            }
        }

        private static List<Player> players = new List<Player>
        {
            new HockeyPlayer
            {
                PlayerId = 1,
                PlayerName = "Mitch marner",
                TeamName = "Toronto Maple Leafs",
                GamesPlayed = 5,
                Assists = 12,
                Goals = 7,
            },
            new BasketballPlayer
            {
                PlayerId = 2,
                PlayerName = "Kyle Lowry",
                TeamName = "Toronto Raptors",
                GamesPlayed = 15,
                FieldGoals = 12,
                ThreePointers = 7,
            },
            new BaseballPlayer
            {
                PlayerId = 3,
                PlayerName = "Jose Bautista",
                TeamName = "Toronto Blue Jays",
                GamesPlayed = 5,
                Runs = 12,
                HomeRuns = 7,
            },
        };

        static void Main(string[] args)
        {
            ViewHockeyPlayer();
        }
    }
}

推荐阅读