TOptional<T>

TOptional<T> — это шаблонный тип, обертка в которую мы оборачиваем нужный нам тип данных, которое может быть установлено или отсутствовать.

Если нам нужно проверить были записаны какие либо данные в переменную или нет.
В обычной ситуации мы создадим новую переменную записываем в нее значения а после сравниваем с «Магическим значением» что обязывает нас помнить и учитывать такие проверки а если их будет несколько риск ошибки на ровном месте возрастает в разы

Пример кода с проверкой на «Магическое значение»

UPROPERTY(EditDefaultsOnly)
TArray<UObject*> ItemSlots;
	
int32 FindFirstEmptySlot()
{
	for (int32 i = 0; i < ItemSlots.Num(); i++)
	{
		if (IsValid(ItemSlots[i]))
		{
			return  i;
		}
	}
	return -1;
}

void AddItemSlot(UObject* NewItem)
{
	int32 EmptySlot = FindFirstEmptySlot();
	if (EmptySlot != -1)
	{
			
	}
}

В этом коде после поиска слота мы должны проверить найден ли он, а для этого нам необходимо сравнить его с каким-то «магическое значение»

  • нужно помнить, что -1 означает «не найдено»
  • для разных типов придётся использовать разные значения
  • легко допустить ошибку при сравнении

TOptional<T> решает эту проблему теперь нам не нужно будет придумывать какие-то значения если мы ничего не нашли теперь у нас есть единообразная проверка для всех подобных случаев и при замене типа нам не нужно будет менять условия во всех местах где использовался этот тип данных

TOptional<int32> FindFirstEmptySlot()
{
	for (int32 i = 0; i < ItemSlots.Num(); i++)
	{
		if (IsValid(ItemSlots[i]))
		{
				return  i;
		}
	}
	return TOptional<int32>();
}

void AddItemSlot(UObject* NewItem)
{
	TOptional<int32> EmptySlot = FindFirstEmptySlot();
	if (EmptySlot.IsSet())
	{
		int32 Value = EmptySlot.GetValue();	
	}
}

Что изменилось

  • код становится чище и безопаснее
  • мы не используем «магические значения»
  • одинаковая проверка для любых типов
  • Вместо «магических значений»
  • нужно явно показать, что результат может быть пустым
  • Когда значение может отсутствовать, но не является ошибкой
  • yже используется указатель
  • когда нет нужды проверять значение есть или нет

⚠️ важно помнить если вы вызовете GetValue() метод для неинициализированного значения то вы получите краш игры или редактора

if (EmptySlot.IsSet())
{
    int32 Value = EmptySlot.GetValue();
}