简体   繁体   English

在 C# 中编写多个构造函数重载的最佳方法

[英]Best way to write multiple constructor overloads in C#

I am learning C# and made a simple "Player" class.我正在学习 C# 并制作了一个简单的“播放器”class。 But I struggle having multiple overload.但我很难有多重超载。 Here's my best solution but I feel like it could be done simpler/better.这是我最好的解决方案,但我觉得它可以做得更简单/更好。

class Player : Entity
    {
        public Player() {
            Name = "Player";
            XP = 0;
            LVL = 1;
            XPToLvlUp = 10;
            XpRank = 10;
        }

        public Player(string name) : this() {
            Name = name;
        }

        public Player(string name, int _Hp, int _Mp) : this(name) {
            HP = _Hp;
            MP = _Mp;
        }

        public Player(string name, int _Hp, int _Mp, int _Xp, int _Lvl) : this(name, _Hp, _Mp) {
            XP = _Xp;
            LVL = _Lvl;
        }

        public Player(string name, int _Hp, int _Mp, int _Xp, int _Lvl, int XpByRank) : this(name, _Hp, _Mp, _Xp, _Lvl) {
            XpRank = XpByRank;
        }

        //deleted code for better reading

        private int XPToLvlUp;
        private int XpRank;
        public int XP;
        public int LVL;
        public string Name;
    }  

Is it good and if not please tell me why.好不好,如果不好请告诉我为什么。 Thanks for your responses!感谢您的回复!

I think it's fine as is.我认为这很好。 One question to ask yourself: Are each of those methods actually likely to be called?要问自己一个问题:这些方法中的每一个是否真的可能被调用?

One option is to just let the programmer set those values after they've instantiated the class:一种选择是让程序员在实例化 class 后设置这些值:

var myPlayer = new Player();
myPlayer.XP = 5;

However, there are situations where you really want all the info up front, so that may not be suitable.但是,在某些情况下,您确实需要预先了解所有信息,因此这可能不合适。

Another option could be an options class that is passed to the ctor:另一个选项可能是传递给 ctor 的选项 class:

public class PlayerSettings
{
  public Name = "Player";
  public XP = 0;
  public LVL = 1;
  public XPToLvlUp = 10;
  public XpRank = 10; 
}

Then your ctors looks like this:然后你的ctors看起来像这样:

public Player() : this(new PlayerSettings())
{
}

public Player(PlayerSettings settings)
{
  //Fill in appropriate variables here
}

That option would be called in this way:将以这种方式调用该选项:

var playerSettings = new PlayerSettings() { XP = 5 };
var myPlayer = new Player(playerSettings());

In the end, I'm not sure one is "better" than the other, it largely depends on your needs.最后,我不确定一个是否比另一个“更好”,这在很大程度上取决于您的需求。

Your class is almost good and acceptable.您的 class 几乎可以接受。

Short story: use Properties.短篇小说:使用属性。

Long story:很长的故事:

First of all make or follow the naming rules, it will make your code more friendly to read.首先制定或遵循命名规则,它会让你的代码更易于阅读。 It's up to you, just a suggestion.这取决于你,只是一个建议。 For complex names consisting of multiple words you may use CamelCasedNames .对于由多个单词组成的复杂名称,您可以使用CamelCasedNames And avoid shorten names for all types of data where it maybe useful.并避免在可能有用的地方缩短所有类型数据的名称。 For example you may expand Lvl to Level but Xp to Experience will look as something odd.例如,您可以将Lvl扩展到Level ,但将Xp扩展到Experience看起来会很奇怪。 It's up to you too.这也取决于你。

string name; // local Variable, first character lower cased
private string _name; // private Field, first character is lower cased with leading "_"
public string Name { get; set; } // public Property, first character is upper cased

I'll show you alternatives to overriden constructors and will follow the naming rules.我将向您展示替代构造函数的替代方法,并将遵循命名规则。

1) Default values for constructor (with a part of your class to keep it simple) 1)构造函数的默认值(使用 class 的一部分保持简单)

class Player
{
    public Player(string name = "Player", int xp = 0, int level = 1)
    {
        Name = name;
        Xp = xp;
        Level = level;
    }

    // Properties instead of Fields
    public int Xp { get; private set; } // restrict modification of the property outside of a class but reading is available
    public int Level { get; private set; }
    public string Name { get; set; }
} 

2) Properties without constructor with default values 2) 没有带有默认值的构造函数的属性

First Property purpose is restrict access to data to keep internal object data consistent.第一个属性的目的是限制对数据的访问,以保持内部 object 数据一致。 Even you make mistakes in the code.即使你在代码中犯了错误。 Good way to avoid some bugs.避免一些错误的好方法。

Second property purpose is executing code while you're getting or setting one.第二个属性目的是在获取或设置代码时执行代码。 For example, making properties dependent on each other to store less and only unique data.例如,使属性相互依赖以存储更少且仅唯一的数据。

class Player
{
    public int Xp { get; private set; } = 0;
    public int Level { get; private set; } = 1;
    public string Name { get; set; } = "Player";
} 

Usage用法

Player player = new Player() { Name = "KillerPWNZ", Level = 100, Xp = 999999 };

Bonus: Another Property feature奖金:另一个属性功能

You can execute any code in get or set clause.您可以在getset子句中执行任何代码。

Let's assume that each next player's level require doubled amount of xp from previous but 2nd level requre 100 XP.假设每个下一个玩家的级别需要双倍的经验值,但第二级需要 100 经验值。 And you decided to invoice to the 1st leveled player 1000 XP.你决定向第一级玩家开具 1000 XP 的发票。 Obviously you'll need to bump the Level few times.显然,您需要多次调整Level Assuming that Xp contains relative to Level value.假设Xp包含相对于Level的值。

The invoice发票

player.Xp += 1000;

The Property with code带有代码的属性

private int _xp = 0;

public int Level { get; private set; } = 1;
public int Xp
{
    get => _xp; // same as: get { return _xp; }
    set
    {
        _xp = value; // here value is keyword containing data you want to set
        while (_xp >= GetXpPerLevel(Level))
        {
            _xp -= GetXpPerLevel(Level);
            Level++;
        }
        while (_xp < 0 && Level > 1)
        {
            _xp += GetXpPerLevel(Level - 1);
            Level--;
        }
    }
}

// helper method
private int GetXpPerLevel(int level)
{
    if (level < 1) return 0;

    // int result = 100;
    // for (int i = 1; i < level; i++) result *= 2;
    // return result;

    // or the same with some binary shift magic :)
    return 100 << (level - 1);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM