簡體   English   中英

比較枚舉的更快方法?

[英]Faster way to compare enums?

我正在尋找比較枚舉的更好方法。 當前,我有一個帶有3個不同可能值的枚舉:

public enum Elements { fire, water, earth };

但是,有一個函數示例,其中兩個元素碰撞時會發生某些事情:

Public Void ElementCollisionExample(Elements element1, Elements element2){

  if (element1 == Elements.fire){
    if (element2 == Elements.fire){
      //Do stuff
    } else if (element2 == Elements.water){
      // Do stuff
    } else {
      // Do stuff
    }
  } else if (element2 == Elements.water){...etc...}
}

那僅用於火元素!

我搜索了一會兒,並查看了類似的SO問題,但不確定如何提出問題。 我發現的只是諸如“比對Enum更快的'=='或'.Equals()'之類的問題,這是完全不同的。

是否有捷徑可尋? 我已經在單獨的Manager中處理了這些條件,但仍然讓我感到惱火。

編輯:元素的組合始終具有相同的結果。 因此,火+水= X,水+火= X也是如此。

它將是C#7.0中引入的帶有C#開關條件的更簡潔的代碼。

public void ElementCollisionExample(Elements element1, Elements element2)
{
    // Do nothing on equal elements
    if (element1 == element2) return;

    switch (element1)
    {
        case Elements.fire when element2 == Elements.water:
        case Elements.water when element2 == Elements.fire:
            // Do stuff
            break;
        case Elements.fire when element2 == Elements.earth:
        case Elements.earth when element2 == Elements.fire:
            // Do stuff
            break;
        case Elements.water when element2 == Elements.earth:
        case Elements.earth when element2 == Elements.water:
            // Do stuff
            break;
    }
}

已更新: element1element2順序無關緊要。 也忽略了相等的元素。

假設元素的組合順序無關緊要,則可以將枚舉視為一個位字段,即一組標志-這樣就可以將它們組合在一起,從而實現簡單的switch 例如:

[Flags]
public enum Elements
{
    none = 0b0000_0000_0000,
    fire = 0b0000_0000_0001,
    water = 0b0000_0000_0010,
    earth = 0b0000_0000_0100
};


public void ElementCollisionExample(Elements element1, Elements element2)
{
    switch (element1 | element2)
    {
        case Elements.fire | Elements.water:

            Console.WriteLine("The fire is extinguished");
            break;
        case Elements.earth | Elements.fire:

            Console.WriteLine("The earth goes black");
            break;
    }
}

一種選擇是擁有可以調用的動作字典。 例如:

public class ElementActionFactory
{
    // Somewhere to keep our actions, using tuple to pair up elements
    private Dictionary<(Elements, Elements), Action> _elementActions;

    public ElementActionFactory()
    {
        // Initialise the action dictionary
        _elementActions = new Dictionary<(Elements, Elements), Action>
        {
            {(Elements.Fire, Elements.Fire), FireAndFire},
            {(Elements.Fire, Elements.Water), FireAndWater},
            {(Elements.Fire, Elements.Earth), FireAndEarth},
            // etc.
        };
    }

    public void Invoke(Elements element1, Elements element2)
    {
        // Try to get the action, and if we don't find it...
        if (!_elementActions.TryGetValue((element1, element2), out var action))
        {
            // reverse the arguments and try again - this assumes the order is not important
            if (!_elementActions.TryGetValue((element2, element1), out action))
            {
                return; //No action was found
            }
        }

        // Actually run the method now
        action.Invoke();
    }

    public void FireAndFire()
    {
        Console.WriteLine("Fire And Fire");
    }

    public void FireAndWater()
    {
        Console.WriteLine("Fire And Water");
    }

    public void FireAndEarth()
    {
        Console.WriteLine("Fire And Earth");
    }
}

要使用它,它很簡單:

var elementActionFactory = new ElementActionFactory();

var element1 = Elements.Fire;
var element2 = Elements.Water;

elementActionFactory.Invoke(element1, element2);

對於清潔代碼,我建議使用復雜的開關...

Elements x, y;
        switch (x)
        {
            case Elements.fire:
                switch (y)
                {
                    case Elements.fire:
                        break;
                    case Elements.water:
                        break;
                    case Elements.earth:
                        break;
                }
                break;
            case Elements.water:
                switch (y)
                {
                    case Elements.fire:
                        break;
                    case Elements.water:
                        break;
                    case Elements.earth:
                        break;
                }
                break;
            case Elements.earth:
                switch (y)
                {
                    case Elements.fire:
                        break;
                    case Elements.water:
                        break;
                    case Elements.earth:
                        break;
                }
                break;
        }

使用元組,可以避免嵌套ifs:

public void ElementCollisionExample(Elements element1, Elements element2)
 {
 Tuple<Elements,Elements> elements = Tuple.Create(element1,element2);
 if(elements.Equals(Tuple.Create(Elements.fire, Elements.earth))
  {
  //do something
  }
 else if(elements.Equals(Tuple.Create(Elements.fire, Elements.water))
  {
  // do something
  }
 // and so on
}

如果創建單獨的函數,則可以進一步簡化它:

public void ElementCollisionExample(Elements element1, Elements element2)
 {
 Tuple<Elements,Elements> elements = Tuple.Create(element1,element2);
 if(CompareElements(elements, Elements.fire, Elements.earth))
  {
  //do something
  }
 else if(CompareElements(elements, Elements.fire, Elements.water))
  {
  // do something
  }
 // and so on
}

private bool CompareElements(Tuple<Elements,Elements> actual, Elements expected1, Elements expected2)
 {
 return actual.Equals(Tuple.Create(expected1, expected2));
 }

我發現枚舉鏈接到整數。 因此,就我而言,我可以使用以下方法:

if ((int)element1 + (int)element2 == 3){
  //Do stuff
}

在這種情況下,水(1)和土(2)的任何組合都將導致3,並觸發條件。

感謝每個人使用不同的方法,這將對無法使用我的方法找到該問題的人有所幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM