Есть один подлый случай, когда return
в обычном методе и return await
в async
метод ведут себя по-разному: в сочетании с using
(или, более общо, любой return await
в блоке try
), .
Рассмотрим эти две версии метода:
Task<SomeResult> DoSomethingAsync()
{
using (var foo = new Foo())
{
return foo.DoAnotherThingAsync();
}
}
async Task<SomeResult> DoSomethingAsync()
{
using (var foo = new Foo())
{
return await foo.DoAnotherThingAsync();
}
}
Первый метод будет Dispose()
объектом Foo
, как только метод DoAnotherThingAsync()
вернется, что вероятно, задолго до его завершения. Это означает, что первая версия, вероятно, глючит (потому что Foo
находится слишком рано), а вторая версия будет работать нормально.
Вы можете справиться с этим с некоторой чертой. Определите
// Primary template
template <class T>
struct Table_Trait;
// Specialization
template <>
struct Table_Trait<int> { using type = Table_Inside_int; };
template <>
struct Table_Trait<char> { using type = Table_Inside_char; };
template <class T>
using Table_Inside_t = typename Table_Trait<T>::type;
и используйте его через
template<class T>
class Table {
Table_Inside_t *tmp;
};
Однако, может быть более простое решение, если нет необходимости иметь независимые классы Table_Inside_int
и Table_Inside_double
. Вы можете использовать специализацию также непосредственно
// Primary template
template <class T>
class Table_Inside;
// Specialization
template <>
class Table_Inside<int> { /* implementation for int */ };
template <>
class Table_Inside<char> { /* implementation for char */ };
Это легко сделать с помощью специализации :
// The "base" generic case
template<typename T>
class Table_Inside;
template<>
class Table_Inside<char>
{
// Special implementation for characters
};
template<>
class Table_Inside<int>
{
// Special implementation for integers
};
template<typename T>
class Table
{
Table_Inside<T>* tmp;
};
Если вам нужна общая функциональность, совместно используемая классами char
и int
, то вы можете использовать наследование для этого .
Если специализация не совсем работает и существует только пара типов, псевдоним можно создать, используя std::conditional
и std::is_same
:
// assumes only char or int will be passed
template <class T>
using Table_Inside = std::conditional_t<std::is_same_v<T, char>, Table_Inside_char, Table_Inside_int>;
[ 117] Это можно использовать так же, как и раньше, как Table_Inside<T>
.