Лучший метод, чем длинные операторы if в Unity c#

#c# #unity3d #if-statement

#c# #unity3d #оператор if

Вопрос:

Я работаю над игрой, в которой у меня есть канон, который срабатывает в разное время. Вместо написания длинного оператора if, подобного этому:

 If (time == 1) {
    "Do something "
} else If (time == 2) {
    "Do something else "
} else If (time == 3) {
   " You probaly get the point"
} else { 
   " My real problem is much longer than this. This is just. 
      an. 
    example"
}
  

Так что, если есть более простой и красивый способ сделать это на c #, это было бы здорово. Если нет, дайте мне знать также. Заранее спасибо

Комментарии:

1. Если в соответствии с вашим требованием у него много разных случаев, и запуск должен быть в определенное время, например time == 1 и т.д., Тогда вам нужно использовать операторы условий. вы можете создать для него отдельную функцию, если хотите. Это все, что я могу сказать, не зная фактического сценария.

2. switch Оператор может быть тем, что вы ищете, а может и нет.

3. Я спрашиваю, есть ли способ составить список чисел типа 1, 2, 3. Чем говорить if (time == мой список). Это что-то?

4. Than say if (time == my list). — что вы имеете в виду?

5. является time действительно и int значением?

Ответ №1:

Как упоминалось в комментариях,
использование инструкции Switch, вероятно, является тем, что вы ищете.

     private static void FireCanons(int time)
    {
        switch (time)
        {
            case 1:
                // "do something";
                break;
            case 2:
                // do something else
                break;
            case 3:
                // you probably get the point"
                break;
            default:
                // My real problem is much longer than this. This is just. an. example"
                break;
        }
    }
  

Обновить:
Просто глядя на ваши комментарии, словарь может быть лучше подходит.
Вот краткий пример, который я сделал.

     private static void FireCanons(int time)
    {
        // A Dictionary That Will Hold Our Results.
        var myList = new Dictionary<int, string>
        {
            { 1, "do something" },
            { 2, "do something else" },
            { 3, "you probably get the point" },
            { 4, "My real problem is much longer than this. This is just. an. example" }
        };

            // Attempt To Get The Value.
            if (myList.TryGetValue(time, out string result))
            {
                // Display Results.
                Console.WriteLine(result);
            }
    }
  

Комментарии:

1. Нет необходимости в myList.ContainsKey .

2. да, это верно, я подумал, что он может захотеть выполнить проверку, чтобы увидеть, был ли ключ там в первую очередь.

3. TryGetValue выполняется ли эта проверка. Он возвращает точно такое же значение, как ContainsKey

4. Могу ли я сказать: новый словарь<двойная строка>

5. Вы, конечно, можете 🙂

Ответ №2:

Словарь — это другой подход. Создайте словарь, в котором вы можете регистрировать различные действия для каждого значения time

 void DoSomething()
{
    // Do something
}

void DoSomethingElse()
{
    // Do else
}

void  YouProbalGetThePoint()
{
    //  You probaly get the point
}
  

Регистрация действий

 var actions = new Dictionary<int, Action>
{
    { 1, DoSomething },
    { 2, DoSomethingElse },
    { 3, YouProbalGetThePoint },
    { 4, DoSomething },
}
  

Тогда использование может быть однострочным: ish

 var action = actions.GetValueOrDefault(time, () => {});
action();
  

Такой подход предоставляет возможность изменить поведение вашего кода без изменения кода по принципу открытия-закрытия функции 😉

Комментарии:

1. не GetValueOrDefault возвращает первое значение, если ни одно не может быть найдено?

2. GetValueOrDefault вернет значение, которое вы предоставляете в качестве второго аргумента, в ответе я предоставил лямбда, которые ничего не делают.

3. Разве это в любом случае не возвращало бы не первое значение, а вместо него значение по умолчанию (следовательно, имя), которое было бы просто null ? И чем вы могли бы сделать, action?.Invoke(); поэтому, даже если он вернет null , вы не получите исключения.

4. @derHugo, Dictionary.GetValueOrDefault — метод расширения, который принимает значение по умолчанию в качестве второго аргумента. Возврат значения по умолчанию, которое можно использовать без проверки null, упростит код и сделает жизнь другого разработчика счастливее 😉

5. Я только что указал, что вы могли бы использовать другую перегрузку без предоставления пользовательского значения по умолчанию и в любом случае получите значение по умолчанию. На мой взгляд, было бы более чистым кодом для правильного получения, null если бы не было совпадения, и даже не вызывать действие, если все равно нечего делать 😉 но, возможно, это просто вопрос о стилях кодирования и вкусе 😉 это могло бы измениться, если бы речь шла, например, о float или int , где значения по умолчанию 0 может быть недостаточно для различия между значением по умолчанию и действительным результатом. Там вы могли бы, например, вместо этого захотеть получить отрицательную бесконечность.

Ответ №3:

Текущие ответы в порядке… чтобы ответить на ваш вопрос, time действительно ли это int значение.

Это всего лишь предположение, но обычно, когда вы говорите о, time у вас есть float значение, например, из Time.time .

Для этого ваш подход с использованием == , a switch и a dictionary также был бы совершенно бесполезен, поскольку вероятность того, что точное время, например, 2.0 совпадает в определенном кадре, очень близка к 0 . (даже не говоря о точности с плавающей запятой здесь …)

Для этого вам, скорее всего, захочется взглянуть на сопрограммы и WaitForSeconds

Вы можете создать метод расширения

 public static class MonoBehaviourExtensions
{
    public static void Invoke(this MonoBehaviour me, Action theDelegate, float time)
    {
        me.StartCoroutine(ExecuteAfterTime(theDelegate, time));
    }

    private static IEnumerator ExecuteAfterTime(Action theDelegate, float delay)
    {
        yield return new WaitForSeconds(delay);
        theDelegate?.Invoke();
    }
}
  

и чем просто использовать, например

 private void Start()
{
    this.Invoke(DoSomething, 1);
    this.Invoke(DoSomethingElse, 2);
    this.Invoke(YouGetThePoint, 3);
}

// will be executed 1 second after start
private void DoSomething()
{ ... }

// will be executed 2 seconds after start
private void DoSomethingElse()
{ ... }

// will be executed 3 seconds after start
private void YouGetThePoint()
{ ... }
  

Если вы хотите, чтобы они выполнялись снова после некоторой задержки, вы могли бы просто добавить новый вызов в конце, например

 private void DoSomething()
{ 
    ... 

    this.Invoke(DoSomething, 1);
}
  

или, альтернативно, добавьте другой метод расширения для этого:

 public static class MonoBehaviourExtensions
{
    public static void Invoke(this MonoBehaviour me, Action theDelegate, float time)
    { ... }

    private static IEnumerator ExecuteAfterTime(Action theDelegate, float delay)
    { ...  }

    public static void InvokeRepeated(this MonoBehaviour me, Action theDelegate, float timeInterval)
    {
        StartCoroutine(ExecuteInIntervals(theDelegate, interval));
    }

    private static IEnumerator ExecuteInIntervals(Action theDelegate, float interval)
    {
        while(true)
        {
            yield return new WaitForSeconds(interval);
            theDelegate?.Invoke();
        }
    }
}
  

и чем использовать вместо

 private void Start()
{
    this.InvokeRepeated(DoSomething, 1);
    this.InvokeRepeated(DoSomethingElse, 2);
    this.InvokeRepeated(YouGetThePoint, 3);
}
  

so DoSomething вызывается каждую секунду, DoSomethingElse вызывается каждые 2 секунды и YouGetThePoint вызывается каждые 3 секунды.