【问题标题】:What is the best way to implement a reordering method?实现重新排序方法的最佳方法是什么?
【发布时间】:2014-01-07 08:01:56
【问题描述】:

我有一些代码应该根据给定的顺序为其属性分配一些值。

下面是一些可以完成这项工作的示例代码:

public class AnimalCount
{
    public int Dogs;
    public int Cats;
    public int Fish;
    public int Birds;

    public void RankValues(string first, string second, string third, string fourth)
    {
        string property = "";
        int value = -1;
        for (int i = 0; i < 4; i++)
        {
            switch (i)
            {
                case 0: property = first;  value = 10; break;
                case 1: property = second; value = 12; break;
                case 2: property = third;  value = 19; break;
                case 3: property = fourth; value = 20; break;
            }
            switch (property)
            {
                case "dogs":  Dogs  = value; break;
                case "cats":  Cats  = value; break;
                case "fish":  Fish  = value; break;
                case "birds": Birds = value; break;
            }
        }
    }
}

不过,这段代码存在一些问题。

  1. 主要的问题是如何传递参数。使用这种方法,由于它们是作为字符串传递的,因此我们失去了类型安全性。因此,我们可能有重复或不匹配的字符串。我们可以使用枚举,但仍然存在重复的风险,我们必须进行一些代码重复才能使其正常工作。
  2. 开关很丑。感觉就像是代码重复。

除了用异常处理填充代码之外,还有什么更好的解决方案吗?对我来说似乎非常丑陋。

如果您一定要知道,我正在尝试编写一个函数,该函数采用龙与地下城中要求的能力分数顺序,并按照您选择的顺序为它们滚动。

【问题讨论】:

  • 您使用的是特定语言吗?在我看来是 c#/java 吗?
  • 是的,它是 C#,但这个问题确实适用于任何程序语言
  • c# 是面向对象的而不是过程的。
  • 是的,当我说“程序”时,我的意思是它是“命令式”的同义词,而不是“严格程序”的意思。所有 OO 语言(我所知道的)也是命令式语言。
  • 如果您发布已编译的代码会很好。 :-)

标签: c# code-readability


【解决方案1】:

我会这样做:

public class AnimalCount
{
    public int Dogs;
    public int Cats;
    public int Fish;
    public int Birds;

    private Dictionary<string, Action<int>> rankers
        = new Dictionary<string, Action<int>>()
    {
        { "dogs", v => Dogs = v },
        { "cats", v => Cats = v },
        { "fish", v => Fish = v },
        { "birds", v => Birds = v },
    };

    private Action<string, int> setRank = (t, v) =>
    {
        if (rankers.ContainsKey(t))
        {
            rankers[t](v);
        }
    };

    public RankValues(string first, string second, string third, string fourth)
    {
        setRank(first, 10);
        setRank(second, 12);
        setRank(third, 19);
        setRank(fourth, 20);
    }
}

【讨论】:

  • 好吧,我不久前放弃了这个项目,但我认为这仍然是一个好问题......考虑到时间流逝,我的大脑告诉我,Dict 绝对是要走的路,但可能一种不同的方式......现在发布我自己的答案。
【解决方案2】:

不完全确定我是否在关注你,但你能不能简单地接受 4 个参数的有序集合?

public void doWhatever(String[] orderedParams) {
    this.animals = orderedParams;
    // ... 
    this.doTheThing(animals[0], 10);
    this.doTheThing(animals[1], 12);
    // etc
}

【讨论】:

    【解决方案3】:

    字典将是您的结果的一个很好的容器,因为您本质上想要一个键/值对。如果您将两个集合输入到您的排名函数中

    public Dictionary<string, int> Rank(string[] orderedKeys, int[] orderedValues)
    {
        Dictionary<string, int> rankedDictionary = new Dictionary<string, int>();
        for (int i = 0; i < orderedKeys.Length; i++)
        {
            rankedDictionary.Add(orderedKeys[i], orderedValues[i]);
        }
        return rankedDictionary;
    }
    
    public void CallRank()
    {
        string[] orderedKeys = new[] { "dogs", "cats", "fish", "birds" };
        int[] orderedValues = new[] { 10, 12, 19, 20 };
    
        Dictionary<string,int> rankedResults =  Rank(orderedKeys, orderedValues);
    
        int catsValue = rankedResults["cats"];
    }
    

    我问你是否使用 C# 的原因是因为如果你担心强类型变量,而不是使用 "cat" 和 "dog" 等字符串。你可以在 c# 中使用 Enum。

    http://msdn.microsoft.com/en-us/library/sbbt4032.aspx

    public enum Animals
    {
        Dog
        Cat
        ....
    }
    

    所以你的字典应该是类型

    Dictionary<Animals, int>
    

    你会这样访问它

    int dogValue = rankedDictionary[Animals.Dog];
    

    【讨论】:

    • 是的,我正在考虑使用字典和枚举......但我真的希望那里的公共属性按原样命名。当然,我总是可以使用他们的吸气剂来完成这项工作,但是对于如此简单的事情来说,这似乎太过分了......而且枚举看起来也很愚蠢,因为我想要那里的属性......我想我会坚持什么我原来有
    【解决方案4】:

    从其他答案中汲取灵感,我认为实现这一点的最佳方法如下:

    using System.Collections.Generic;
    public class AnimalCount
    {
        public int Dogs { get { return animals["dogs"]; } }
        public int Cats { get { return animals["cats"]; } }
        public int Fish { get { return animals["fish"]; } }
        public int Birds { get { return animals["birds"]; } }
    
        private Dictionary<string, int> animals = new Dictionary<string, int>();
    
        public void RankValues(string first, string second, string third, string fourth)
        {
            animals[first] = 10;
            animals[second] = 12;
            animals[third] = 19;
            animals[fourth] = 20;
        }
    }
    

    并且使用枚举来保证类型安全:

    using System.Collections.Generic;
    
    public enum Animals
    {
        Dogs, Cats, Fish, Birds
    }
    
    public class AnimalCount
    {
        public int Dogs { get { return animals[Animals.Dogs]; } }
        public int Cats { get { return animals[Animals.Cats]; } }
        public int Fish { get { return animals[Animals.Fish]; } }
        public int Birds { get { return animals[Animals.Birds]; } }
    
        private Dictionary<Animals, int> animals = new Dictionary<Animals, int>();
    
        public void RankValues(Animals first, Animals second, Animals third, Animals fourth)
        {
            animals[first] = 10;
            animals[second] = 12;
            animals[third] = 19;
            animals[fourth] = 20;
        }
    }
    

    【讨论】:

    • 只有四个可能的值,也许枚举不值得。根据 Ben Griffiths 的回答,还允许,对于更多的可能值或任意数量的可能值,传入某种有序参数会更好
    猜你喜欢
    • 2012-04-20
    • 1970-01-01
    • 1970-01-01
    • 2013-03-11
    • 2010-09-09
    • 2015-08-21
    • 1970-01-01
    • 2015-07-06
    相关资源
    最近更新 更多