#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
секунды.