解决 关于类对象实例化的问题

Matthieu.

成员
加入
20月15日,2020年8月15日
消息
23
编程经验
Beginner
嗨埃尔弗里昂,

我有一个问题我想通过使用一个例子来澄清。

我有一个俱乐部班级和一个网球场班级。俱乐部可以有许多网球场合作为该俱乐部的成员,并且一个网球人一次只能成为一个俱乐部的成员。
我的课程会如此。我为此示例简化了类。

C#:
public class Club
    {
        private List<TennisPlayer> members;

        public Club()
        {
            members = new List<TennisPlayer>();
        }

        public void AddTennisPlayerAsMember(TennisPlayer tennisPlayer)
        {
            members.Add(tennisPlayer);
            tennisPlayer.Club = this;
        }
    }


C#:
public class TennisPlayer
    {
        public string Name;
        public Club Club;

        public TennisPlayer(string name, Club club)
        {
            Name = name;
            club.AddTennisPlayerAsMember(this);
        }
    }

所以我的问题是,它是正确的,它是在网球场馆课堂上的现场俱乐部没有像俱乐部俱乐部=新俱乐部()?
原因如果我会这样做,我实例化的每个网球角对象都会有自己的俱乐部对象,这不是逻辑的,因为每个俱乐部只有一个俱乐部对象,就像在现实生活中没有同一个俱乐部的重复一样,我对?
 

约翰

C#论坛主持人
工作人员
加入
2011年4月23日
消息
1,159
地点
挪威
编程经验
10+
它对是它在网球场阶级,现场俱乐部没有像俱乐部俱乐部=新俱乐部()?
那是对的,玩家不应该是创建新俱乐部的界面。

此外,在您的播放器类中,构造函数按参数设置俱乐部。请注意,如果要分配俱乐部,则该参数可能是null,这将导致addTennisplayerAsm呼叫中的NULLReference异常,这可以通过空调运算符轻松处理: 会员访问运算符和表达式 - C#参考
C#:
club?.AddTennisPlayerAsMember(this);
 

Matthieu.

成员
加入
20月15日,2020年8月15日
消息
23
编程经验
Beginner
那是对的,玩家不应该是创建新俱乐部的界面。

此外,在您的播放器类中,构造函数按参数设置俱乐部。请注意,如果要分配俱乐部,则该参数可能是null,这将导致addTennisplayerAsm呼叫中的NULLReference异常,这可以通过空调运算符轻松处理: 会员访问运算符和表达式 - C#参考
C#:
club?.AddTennisPlayerAsMember(this);
感谢您的回答。现在我知道我在很好的轨道上。

现在假设类俱乐部有一个额外的字段名称(俱乐部的名称)。
想象一下,我创建一个俱乐部对象'c'和一个网球名对象't'。通过使用T I链接T到C的构造函数。
Trough T我现在可以达到C并访问字段名称(t.club.name),这样可以好。如果我想知道Tennisplayer对象的俱乐部名称,这是方便的。
但现在我还可以通过T(t.club.addtennisplayerasmmbersmberablebemberablebemberabermberderdembersederdemberse,这不可能。
因为现在我可以使用一个网球字节游戏对象更改俱乐部。
所以我的想法是在网球场馆级私下制作野外俱乐部,所以我不能在他的课外访问,但现在我无法到达俱乐部名称的Tennisplayer对象。
你应该如何照顾这个“问题”。我可以在班上网球场馆中制作一个属性俱乐部名称,并给出这个值,但它看起来有点奇怪或是常见的?
 

约翰

C#论坛主持人
工作人员
加入
2011年4月23日
消息
1,159
地点
挪威
编程经验
10+
字段应始终是私有的,使用属性将字段值(对象状态)公开到外部。属性也可以被声明只读。
 

sh

众所周知的成员
加入
2018年9月5日
消息
1,982
编程经验
10+
您如何计划定义一个网球员是一名成员的每个俱乐部?在您的Club对象中,您没有俱乐部对象代表哪个俱乐部的名称。如果您有多个俱乐部,这将是一个问题。

从您的Tennisplayer类中删除第4行。它没有目的在那里,它打破了单一责任的规则。

您应该考虑使用抽象类来基于其他课堂。我先坐下来写一下。然后当你在头部有它时,用代码写出来。
 

Matthieu.

成员
加入
20月15日,2020年8月15日
消息
23
编程经验
Beginner
字段应始终是私有的,使用属性将字段值(对象状态)公开到外部。属性也可以被声明只读。

我理解我必须使用属性,但我可以“管理俱乐部类的列表成员。

C#:
public class Club
    {
        public string Name;
        public List<TennisPlayer> Members { get; }

        public Club(string name)
        {
            Name = name;
            Members = new List<TennisPlayer>();
        }

        public void AddMember(TennisPlayer tennisPlayer)
        {
            Members.Add(tennisPlayer);
            tennisPlayer.Club = this;
        }

    }

C#:
public class TennisPlayer
    {
        public Club Club { get; set; }

        public TennisPlayer(Club club)
        {
            Club.AddMember(this);
        }
    }

C#:
class Program
    {
        static void Main(string[] args)
        {
            Club club = new Club("Laagland");
            TennisPlayer tennisPlayer = new TennisPlayer(club);
            tennisPlayer.Club.Members.Add(tennisPlayer);
        }
    }

正如您所看到的,通过Tannisplayer对象,我可以达到并改变俱乐部的Memberst列表,玩家是成员的
但我无法宣布会员列表私有,因为我不能通过俱乐部对象重播,这应该是可以的。
 

约翰

C#论坛主持人
工作人员
加入
2011年4月23日
消息
1,159
地点
挪威
编程经验
10+
public List<TennisPlayer> Members { get; }
这意味着列表对象无法从外部设置,仍然可以从外部自由操纵列表的内容。解决此方法的一种方法是将列表保存在私人字段中,使用公共方法添加/删除成员,以及只返回列表内容(作为数组)的副本的readonly属性。
 

约翰

C#论坛主持人
工作人员
加入
2011年4月23日
消息
1,159
地点
挪威
编程经验
10+
一个网球人一次只能成为一个俱乐部的成员
这种限制可以通过将玩家添加到俱乐部的方法来缓解,它已经有一个俱乐部的方法,方法也可以首先从现有的俱乐部移除播放器。
pseudo clode:
tennisPlayer.Club?.RemovePlayer(tennisPlayer);
 

Matthieu.

成员
加入
20月15日,2020年8月15日
消息
23
编程经验
Beginner
这意味着列表对象无法从外部设置,仍然可以从外部自由操纵列表的内容。解决此方法的一种方法是将列表保存在私人字段中,使用公共方法添加/删除成员,以及只返回列表内容(作为数组)的副本的readonly属性。
但是一个网球场馆还有一个俱乐部对象,对吗?因此,如果我将成员列表保留在私人字段中,则正确地将无法再直接更改列表,但现在我可以使用公共方法添加/删除成员来更改列表。这样一个网球人对象罐仍然改变了一个俱乐部。
 

sh

众所周知的成员
加入
2018年9月5日
消息
1,982
编程经验
10+
让每个课程都有一个焦点。单一的目的。
网球员不应该在他们所在的俱乐部举行任何信息。
俱乐部应在俱乐部中没有关于网球运动员的数据。
 

Matthieu.

成员
加入
20月15日,2020年8月15日
消息
23
编程经验
Beginner
让每个课程都有一个焦点。单一的目的。
网球员不应该在他们所在的俱乐部举行任何信息。
俱乐部应在俱乐部中没有关于网球运动员的数据。
我是SRP的新手,也是一个新手 :)。但想象一下班级作者和一本班级书。一本书确实有一个作者所以一本书类包含作者对象,对吧?
在SRP之后,我可能不会在书CLA中声明作者对象?我发现它肯定是oop中的初学者奇怪的奇怪。
 

sh

众所周知的成员
加入
2018年9月5日
消息
1,982
编程经验
10+
但想象一下班级作者和一本班级书。一本书确实有一个作者所以一本书类包含作者对象,对吧?
这就是我们有时使用抽象的原因。但是,如果您想保留SRP,那么您将重视您的课程严格地了解其目的的细节。在您的情况下,他们似乎是关于A)的详细信息,以及B)网球运动员。

您可以使用多种方式执行您正在进行的内容,包括使用继承,从另一个类继承对象值,同时保持相对于SRP。

你可以写的一种方式是,它将是以下代码。创建一个Club对象,只使用创建Club对象所需的内容,在此示例中,我将使用三个属性。代码被评论,以便您可以将鼠标悬停在VS中,它会告诉您每个部件正在做什么:
C#:
    public class Club
    {
        public string ClubName { get; set; }
        public string ClubAddress { get; set; }
        public string ClubPhoneNumber { get; set; }
        /// <summary>
        /// The Club class is inisialised with a new instance of a club object and its details are provided upon instanciation.
        /// </summary>
        /// <param name="clubName">The name of the club is provided here</param>
        /// <param name="clubAddress">The club address is provided here</param>
        /// <param name="clubPhoneNumber">The clubs phone number is provided here</param>
        public Club(string clubName, string clubAddress, string clubPhoneNumber)
        {
            ClubName = clubName ?? throw new ArgumentNullException(nameof(clubName));
            ClubAddress = clubAddress ?? throw new ArgumentNullException(nameof(clubAddress));
            ClubPhoneNumber = clubPhoneNumber ?? throw new ArgumentNullException(nameof(clubPhoneNumber));
        }
    }
接下来,您需要来自网球员的同样的东西;名称,地址,也许是电话号码......
C#:
    public class TennisPlayer
    {
        public string PlayerName { get; set; }
        public string PlayerAddress { get; set; }
        public string PlayerPhoneNumber { get; set; }
        /// <summary>
        /// The TennisPlayer class is inisialised with a new instance of a TennisPlayer object and its details are provided upon instanciation.
        /// </summary>
        /// <param name="playerName">The name of your tennis player</param>
        /// <param name="playerAddress">The address of your tennis player</param>
        /// <param name="playerPhoneNumber">The phone number of your tennis player</param>
        public TennisPlayer(string playerName, string playerAddress, string playerPhoneNumber)
        {
            PlayerName = playerName ?? throw new ArgumentNullException(nameof(playerName));
            PlayerAddress = playerAddress ?? throw new ArgumentNullException(nameof(playerAddress));
            PlayerPhoneNumber = playerPhoneNumber ?? throw new ArgumentNullException(nameof(playerPhoneNumber));
        }
    }
接下来,您想要某种类型的控制器类。您可以在俱乐部添加和删除网球播放器的东西。我还建议的是为所有数据添加模型类。然后,此模型将与您的UI绑定。但这在此示例中尚未实施。这里的主要目的是展示将​​类对象相对于它们所代表的内容保持:
C#:
    /// <summary>
    /// Here you can use an additional class to work with the objects of your other classes; such as Club, and TenniPlayer.
    /// This class can add your tennis players to a list of tuple TennisPlayer, Club. When this class is first instanciated,
    /// keep a copy of the instanciated object to pass around your application. New instances of this class will create a new instance of _PlayerClubPair.
    /// </summary>
    public class WithMembersOfClubs
    {
        /// <summary>
        /// This list keeps track of your tenis players and the clubs they are in.
        /// </summary>
        private List<Tuple<TennisPlayer, Club>> _PlayerClubPair = new List<Tuple<TennisPlayer, Club>>();
        /// <summary>
        /// This method will add players to your _PlayerClubPair list and store the values of your tennis player and club in a tuple<Tuple<TennisPlayer, Club>>.
        /// </summary>
        /// <param name="tennisPlayer">This is where you pass in the tennis player object</param>
        /// <param name="clubName">This is where you pass in the club object</param>
        public void AddTennisPlayerAsMember(TennisPlayer tennisPlayer, Club clubName)
        {
            _PlayerClubPair.Add(Tuple.Create(tennisPlayer, clubName));
        }
        /// <summary>
        /// This method will remove all references of a TennisPlayer object where the tuple item variable matches the tennisPlayer.Player name variable.
        /// </summary>
        /// <param name="tennisPlayer">This is where you pass in the tennis player you wish to remove</param>
        public void RemoveTennisPlayerAsMember(TennisPlayer tennisPlayer)
        {
            _PlayerClubPair.RemoveAll(t => t.Item1.PlayerName == tennisPlayer.PlayerName);
        }
        /// <summary>
        /// This method allows you to check the number of members in a given club object.
        /// </summary>
        /// <param name="clubName">The name of the club you want to check the number of players in</param>
        /// <param name="number">The number variable will be used to count how many members are in a given club</param>
        /// <returns></returns>
        public int NumberOfMembers_In(string clubName, int number)
        {
            number += (_PlayerClubPair.Where(club => club.Item2.ClubName == clubName)).Count();
            return number;
        }
要使用此代码,您只需要调用Club和Tennisplayer对象的构造函数,并将其传递给数据的另一个类"managed"与控制器一样将在Web应用程序中管理数据,并且从那里开始,您通常会更新模型,并且正如我所说,那么该模型将绑定到您的UI,其中您的UI将在输入的新数据时自动更新您的UI。运行代码的样本如下:
C#:
            Club club = new Club("Bondi Club", "33 Bondibeach Park", "0123456789");
            TennisPlayer tennisPlayer1 = new TennisPlayer("Sheepings", "Sheep ville", "0234567890");

            WithMembersOfClubs membersOfClubs = new WithMembersOfClubs();
            membersOfClubs.AddTennisPlayerAsMember(tennisPlayer1, club);
            TennisPlayer tennisPlayer2 = new TennisPlayer("Bob", "Bob ville", "3214567890");
            membersOfClubs.AddTennisPlayerAsMember(tennisPlayer2, club);

            Debug.WriteLine(string.Join(" ", $"{club.ClubName} has", membersOfClubs.NumberOfMembers_In(club.ClubName, 0), "Members"));

            membersOfClubs.RemoveTennisPlayerAsMember(tennisPlayer1);

            Debug.WriteLine(string.Join(" ", $"{club.ClubName} has", membersOfClubs.NumberOfMembers_In(club.ClubName, 0), "Members"));

您应该阅读的进一步参考是:
.


笔记;虽然我在这个例子中没有进入抽象,但我确实保持了相对较近您已经构建了代码的方式。但是,您可以使用抽象数据层,仍然达到相同的目标。这种方法与上面的例子完全不同,但仍然值得自己教育。
 

跳伞运动员

工作人员
加入
2019年4月6日
消息
2,892
地点
切萨皮克,va.
编程经验
10+
我从第1篇文章中的理解是他想模拟这种关系:
screenshot_5.png.


网球人有0或1个俱乐部。
俱乐部有0个或更多的网球场。

换句话说,网球人只能属于一个俱乐部,俱乐部可以有多个网球运动员。此外,Tennisplayer知道他所属的哪个俱乐部,俱乐部知道哪个网球运动员是成员。


实现#15结束如下所示:
screenshot_6.png.

A与membersofclubs有0个或更多元组<TennisPlayer, Club>.
一个元组<TennisPlayer, Club>有1个网球场和1个俱乐部。

网球运动员现在不知道他/她属于哪个俱乐部,俱乐部不知道哪个网球运动员是其成员。 Whomever正在编写代码现在必须参考第3个对象:withmembersofclubs对象找出会员信息。此外,除非将额外的代码添加到emembersofclub中,否则缺少Tennisplayer最多可以属于大多数俱乐部的强制。

这有几个原因让我难过。首先,它突然更加复杂。我们开始使用两堂课的地方,现在我们最多4个课程。其次,我们现在正在为关系数据库设计,而不是首先启动对象。上面的第一个UML图表显示了一个纯粹的对象面向对象的东西,但第二图是对当前世界的让步我们生活在最终将持续到一个关系数据库中的地方。如果人们使用真正的面向对象的数据库,或者具有非常智能的ORM(对象到关系映射器),那么就没有必要记录TennisPlayer和Club之间的关系 - (面向对象)数据库搞定此事。

有些人可能会争辩说,第一个UML图是一种过用的应用。它隐藏了俱乐部内使用的网球场所列表。好的,这是一个简化的视图,显示细节级别:
screenshot_7.png.

但是,鹅也有好处对雄鹅也有好处,所以让我们展示了与membersofclubs内部的元组列表:
screenshot_8.png.


无论如何,这就是我将处理Tennisplayer和Club的方式:
C#:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

class TennnisPlayer
{
    public string Name { get; set; }

    Club _club;
    public Club Club
    {
        get => _club;

        set
        {
            if (value != _club)
            {
                var oldClub = _club;
                _club = null;
                oldClub?.RemoveMember(this);
                _club = value;
                _club?.AddMember(this);
            }
        }
    }

    public TennnisPlayer(string name, Club club = null)
    {
        Name = name;
        Club = club;
    }

    public override string ToString()
        => $"{Name} ({Club?.Name})";
}

class Club
{
    public string Name { get; set; }
    
    List<TennnisPlayer> _members = new List<TennnisPlayer>();
    public IEnumerable<TennnisPlayer> Members { get => _members; }

    public Club(string name)
    {
        Name = name;
    }

    public void AddMember(TennnisPlayer player)
    {
        if (!_members.Contains(player))
        {
            _members.Add(player);
            player.Club = this;
        }
    }

    public void RemoveMember(TennnisPlayer player)
    {
        if (_members.Contains(player))
        {
            _members.Remove(player);
            player.Club = null;
        }
    }

    public override string ToString()
        => $"{Name}'s Members: " + string.Join(",", Members);
}

class Program
{
    static void Main()
    {
        var clubA = new Club("A");
        var clubB = new Club("B");
        Console.WriteLine(clubA);
        Console.WriteLine(clubB);

        var bjorn = new TennnisPlayer("Bjorn Borg");
        bjorn.Club = clubA;
        Console.WriteLine(bjorn);
        Console.WriteLine(clubA);
        Console.WriteLine(clubB);

        bjorn.Club = clubB;
        Console.WriteLine(bjorn);
        Console.WriteLine(clubA);
        Console.WriteLine(clubB);

        bjorn.Club = null;
        Console.WriteLine(bjorn);
        Console.WriteLine(clubA);
        Console.WriteLine(clubB);

        var john = new TennnisPlayer("John McEnroe", clubA);
        Console.WriteLine(john);
        Console.WriteLine(clubA);
        Console.WriteLine(clubB);

        john.Club = clubB;
        Console.WriteLine(john);
        Console.WriteLine(clubA);
        Console.WriteLine(clubB);

        john.Club = null;
        Console.WriteLine(john);
        Console.WriteLine(clubA);
        Console.WriteLine(clubB);
    }
}
 

sh

众所周知的成员
加入
2018年9月5日
消息
1,982
编程经验
10+
我觉得你经历了所有解释的悲伤,因为我对董事会不同意的是,关于这是如何或者应该做的。你上面制作的要点;我不同意,我真的不在乎进一步与你讨论。当我花了足够的时间讨论了董事会。

每个人都有自己的写作代码方式,我们中的一些人喜欢遵循他人的某些原则,这也很好。所以而不是越来越努力,试图做出一个大的磨难,只要接受你有你的申请,因为你也证明了你的申请,并且知道我有自己的方式。董事会已经讨论了这些要点。

要说,每个元组之间的关系都是荒谬的,也是错误的,也不是非由关联所代表的网球场播和俱乐部的关系。因为他们显然是。它们存储在列表中,就像您巧妙地演示一样。列表中的每个条目都包含一个元组<tennisplayer, club>并防止一名参与者是成员或任何俱乐部两次,可以使用简单的LINQ语法完成,因为我在提出的代码中从俱乐部删除了俱乐部时完成的。它需要很少的努力来阻止用户被允许进入列表,一点检查。

我支持我的推理,没有理由每个对象应该持有任何数据 - 是它是一个网球场馆的列表,或俱乐部列表。他们不需要彼此了解,如果你真的想要它们,你应该使用继承。您目前建议的内容也击败了一个单一目的的目的。最后,如果你仔细看着我的榜样,它会让你带一个对象,而不是四个。 用姆梅伯因克劳布斯 是您唯一需要通过其寿命期间的唯一一个对象,或者在您需要使用其中所定义的列表时需要长时间的生命周期。我设想使用我提供的榜样的凡人在函数中创建实例化对象的常识,其中他们将在俱乐部或网球播放器详细信息中返回函数返回任何一个对象。

无论哪种方式,这是我将在董事会中争论这些点的主题时的能量。快乐的编程,每个人都是他们自己的,毕竟它们都是以不同的方式设计的对象。
 

sh

众所周知的成员
加入
2018年9月5日
消息
1,982
编程经验
10+
@matthieu. - 跳转到最后一个代码块,以查看主源代码块,并保存读取它的工作原理以及我更改的内容。

这是我所做的先前版本的改进。我切换了元组(不是因为使用它们有什么问题) - 没有,但是因为我在以下示例中没有使用列表。我正在切换类型。我以前使用列表的唯一原因是因为OP想要使用列表,以及该示例的拟合的元组。我也可以用一个 sortedlist. 这允许您添加keyValuePair。无论如何,我切换了该列表以获取并发的<TennisPlayer, Club>。 ConcurrentDictionary允许您与任何线程与它们交互,它们是线程安全词典。我主要在标准字典中选择了这个词典,因为它允许你到tryadd / tryremove 基本上防止添加重复的条目,即。在添加用户两次或阻止它们在其他俱乐部分开的情况下:
C#:
            if (membersOfClubs.AddTennisPlayerAsMember(tennisPlayer1, club))
                Debug.WriteLine(string.Join(" ", tennisPlayer1.PlayerName, "joined", club.ClubName));
            if (membersOfClubs.AddTennisPlayerAsMember(tennisPlayer1, club))
                Debug.WriteLine(string.Join(" ", tennisPlayer1.PlayerName, "joined", club.ClubName));
额外的便利性ryadd / tryremove 是他们在执行时返回BOOL,这使得这使得可以方便地检查成功的参赛作品。这也解决了允许成员成为多个俱乐部的一部分的问题(而前一个示例并没有阻止这一点,除非您将支票放置待办事项)。如注意;那个 TAYADD 如果尚未添加了一个新的网球播放器,则只会添加新网球播放器,并调用此方法返回Bool值。

我也会整理LINQ表达,这对给定俱乐部的成员进行计数。通过将where子句与计数组合来完成。此外,我添加了一个新功能,返回来自给定俱乐部的网球运动员的成员名称列表。您可以查看以下示例,仍然可以删除网球播放器类或俱乐部类别彼此了解的必要性。我写它的原因是因为两个类只需要根据OP创建一个值或两个值,即。俱乐部名称,俱乐部地址等之前我正在使用构造函数来代替这些功能来创建新的播放器或俱乐部并将其返回给呼叫代码。自从改变该代码以来,以来:
C#:
        public TennisPlayer InitializeNewPlayer(string playerName, string playerAddress, string playerPhoneNum) => new TennisPlayer
        {
            PlayerName = playerName,
            PlayerAddress = playerAddress,
            PlayerPhoneNumber = playerPhoneNum
        };
        public Club InitializeNewClub(string clubName, string clubAddress, string clubPhoneNum) => new Club
        {
            ClubName = clubName,
            ClubAddress = clubAddress,
            ClubPhoneNumber = clubPhoneNum
        };
返回类型后,您可以尝试将该新播放器添加到您的集合中。关于这个系列的另一个好处是你也可以使用 icollection. 和迭代集合的其他接口(我没有实现它)。我更愿意使用这些课程的另一个原因是因为我设计了它们,是因为俱乐部和网球人士都有一个 单一目的此目的是为每个新玩家/俱乐部的细节提供新的参考。这使我们留下了一个单一的对象,它将包含所有网球运动员和他们所代表的俱乐部。那个课程是: 用姆梅伯因克劳布斯。这是一个完整的例子:

主代码块:
C#:
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

namespace WPFDataBinding
{
    public partial class Window1
    {
        public Window1()
        {
            InitializeComponent();
            WithMembersOfClubs membersOfClubs = new WithMembersOfClubs();

            /* Create your first club */
            Club club = membersOfClubs.InitializeNewClub("Bondi Club", "33 Bondibeach Park", "0123456789");
            /* Create your first player */
            TennisPlayer tennisPlayer1 = membersOfClubs.InitializeNewPlayer("Sheepings", "Sheep ville", "0234567890");

            /* If member does not exist, write that he joined the club */
            if (membersOfClubs.AddTennisPlayerAsMember(tennisPlayer1, club))
                Debug.WriteLine(string.Join(" ", tennisPlayer1.PlayerName, "joined", club.ClubName));

            /* Create your second player */
            TennisPlayer tennisPlayer2 = membersOfClubs.InitializeNewPlayer("Bob", "Bob ville", "3214567890");

            /* If member does not exist, write that he joined the club */
            if (membersOfClubs.AddTennisPlayerAsMember(tennisPlayer2, club))
                Debug.WriteLine(string.Join(" ", tennisPlayer2.PlayerName, "joined", club.ClubName));

            /* Lets display the number of members in a given club */
            Debug.WriteLine(string.Join(" ", club.ClubName, "has", membersOfClubs.NumberOfMembers_In(club.ClubName, 0), "Members"));

            /* Print the names of the players of a given club from the returned list */
            membersOfClubs.ListOfPlayerNames_By("Bondi Club").ForEach((string name) => Debug.WriteLine($"Member : {name}"));

            /* Remove the member from the given club if they exist */
            if (membersOfClubs.RemoveTennisPlayerAsMember(tennisPlayer1))
                Debug.WriteLine(string.Join(" ", tennisPlayer1.PlayerName, "left", club.ClubName));

            /* How many members remain after removing one? */
            Debug.WriteLine(string.Join(" ", club.ClubName, "has", membersOfClubs.NumberOfMembers_In(club.ClubName, 0), "Members"));
        }
    }
    public class Club
    {
        public string ClubName { get; set; }
        public string ClubAddress { get; set; }
        public string ClubPhoneNumber { get; set; }
    }
    public class TennisPlayer
    {
        public string PlayerName { get; set; }
        public string PlayerAddress { get; set; }
        public string PlayerPhoneNumber { get; set; }
    }
    /// <summary>
    /// Here you can use an additional class to work with the objects of your other classes; such as Club, and TenniPlayer.
    /// This class can add your tennis players to a ConcurrentDictionary<TennisPlayer, Club>. When this class is first instantiated,
    /// keep a copy of the instantiated object to pass around your application. New instances of this class will create a new instance of _PlayerClubPair.
    /// </summary>
    public class WithMembersOfClubs
    {
        /// <summary>
        /// This Concurrent Dictionary keeps track of your tenis players and the clubs they are in.
        /// </summary>
        private readonly ConcurrentDictionary<TennisPlayer, Club> _PlayerClubPair = new ConcurrentDictionary<TennisPlayer, Club>();
        /// <summary>
        /// The TennisPlayer is initialised with a new instance of a TennisPlayer object and its details are provided upon instantiation.
        /// </summary>
        /// <param name="playerName">The name of your tennis player</param>
        /// <param name="playerAddress">The address of your tennis player</param>
        /// <param name="playerPhoneNum">The phone number of your tennis player</param>
        /// <returns>Returns the TennisPlayer you created</returns>
        public TennisPlayer InitializeNewPlayer(string playerName, string playerAddress, string playerPhoneNum) => new TennisPlayer
        {
            PlayerName = playerName,
            PlayerAddress = playerAddress,
            PlayerPhoneNumber = playerPhoneNum
        };
        /// <summary>
        /// The Club class is initialised with a new instance of a club object and its details are provided upon instantiation.
        /// </summary>
        /// <param name="clubName">The name of the club is provided here</param>
        /// <param name="clubAddress">The club address is provided here</param>
        /// <param name="clubPhoneNum">The clubs phone number is provided here</param>
        /// <returns>Returns the Club you created</returns>
        public Club InitializeNewClub(string clubName, string clubAddress, string clubPhoneNum) => new Club
        {
            ClubName = clubName,
            ClubAddress = clubAddress,
            ClubPhoneNumber = clubPhoneNum
        };
        /// <summary>
        /// This method will add players to your _PlayerClubPair collection and store the values of your tennis player and club in a key value pair <TennisPlayer, Club>.
        /// </summary>
        /// <param name="tennisPlayer">This is where you pass in the tennis player object</param>
        /// <param name="clubName">This is where you pass in the club object</param>
        public bool AddTennisPlayerAsMember(TennisPlayer tennisPlayer, Club clubName) => _PlayerClubPair.TryAdd(tennisPlayer, clubName);
        /// <summary>
        /// This method will remove all references of a TennisPlayer object passed into it.
        /// </summary>
        /// <param name="tennisPlayer">This is where you pass in the tennis player you wish to remove</param>
        public bool RemoveTennisPlayerAsMember(TennisPlayer tennisPlayer) => _PlayerClubPair.TryRemove(tennisPlayer, out _);
        public List<string> ListOfPlayerNames_By(string clubName) => (_PlayerClubPair.Where(pair => pair.Value.ClubName == clubName).Select(pair => pair.Key.PlayerName)).ToList();
        /// <summary>
        /// This method allows you to check the number of members in a given club object.
        /// </summary>
        /// <param name="clubName">The name of the club you want to check the number of players in</param>
        /// <param name="number">The number variable will be used to count how many members are in a given club</param>
        /// <returns></returns>
        public int NumberOfMembers_In(string clubName, int number)
        {
            number += _PlayerClubPair.Values.Count(club => club.ClubName == clubName);
            return number;
        }
    }
}

输出 :
C#:
sh joined Bondi Club
Bob joined Bondi Club

Bondi Club has 2 Members

Member : Bob
Member : Sheepings

Sheepings left Bondi Club

Bondi Club has 1 Members

整理起来...
我所做的方式这主要是一个偏好的问题,并且坚持在可能的情况下让课程有一个目的。我始终提倡创建基于上下文信息的类,如在该上下文中留下的名称和地址,以便他们保留他们的单一用途目的。这不会使其他人提供的上述建议无效。也许他们不关心我的方式写作代码。那也很好。我们每个人都有我们自己的原则和规则,我们喜欢突破,而且我相信我们都有规则我们也想在它真正方便的时候打破。有时我们需要同意不同意,因为当事情的功能只是有效时,通常没有正确或错误的方法。
 
最佳 底部