Void в C# генерики?
у меня есть универсальный метод, который принимает запрос и выдает ответ.
public Tres DoSomething<Tres, Treq>(Tres response, Treq request)
{/*stuff*/}
но мне не всегда нужен ответ на мой запрос, и я не всегда хочу подавать данные запроса, чтобы получить ответ. Я также не хочу копировать и вставлять методы полностью, чтобы внести незначительные изменения. То, что я хочу, это быть в состоянии сделать это:
public Tre DoSomething<Tres>(Tres response)
{
return DoSomething<Tres, void>(response, null);
}
возможно ли это каким-то образом? Кажется, что конкретно использование void не работает, но я надеюсь найти что-то похожее.
6 ответов:
вы не можете использовать
void, но вы можете использоватьobject: Это небольшое неудобство, потому что ваш потенциальный -voidфункции должны возвращатьnull, но если он унифицирует ваш код, это должна быть небольшая цена.это неспособность использовать
voidкак тип возврата по крайней мере частично отвечает за разделение междуFunc<...>иAction<...>семьи общих делегатов: если бы можно было вернутьсяvoid, всеAction<X,Y,Z>стало бы простоFunc<X,Y,Z,void>. К сожалению, это невозможно.
нет, к сожалению, нет. Если
voidбыли "реальным" типом (напримерunitв F#, например) жизнь была бы намного проще во многих отношениях. В частности, нам не понадобятся обаFunc<T>иAction<T>семьи - там просто будетFunc<void>вместоAction,Func<T, void>вместоAction<T>etc.кроме того, асинхронность проще - не было бы необходимости необщего
Taskтип вообще-мы бы простоTask<void>.к сожалению, это не так, как работают системы типа C# или .NET...
вот что вы можете сделать. Как сказал @JohnSkeet, в C# нет типа блока, так что сделайте это сами!
public sealed class ThankYou { private ThankYou() { } private readonly static ThankYou bye = new ThankYou(); public static ThankYou Bye { get { return bye; } } }теперь вы всегда можете использовать
Func<..., ThankYou>вместоAction<...>public ThankYou MethodWithNoResult() { /* do things */ return ThankYou.Bye; }или использовать что-то уже сделанное командой Rx: http://msdn.microsoft.com/en-us/library/system.reactive.unit%28v=VS.103%29.aspx
вы могли бы просто использовать
Objectкак предлагали другие. ИлиInt32который я видел некоторое использование. ИспользуяInt32вводит "фиктивный" номер (используйте0), но, по крайней мере, вы не можете положить большой и экзотический объект вInt32ссылка (структуры запечатаны).вы также можете написать свой собственный тип "void":
public sealed class MyVoid { MyVoid() { throw new InvalidOperationException("Don't instantiate MyVoid."); } }
MyVoidссылки разрешены (это не статический класс), но может бытьnull. Конструктор экземпляра является частным (и если кто-то пытается вызовите этот частный конструктор через отражение, исключение будет брошено на них).
мне нравится идея Алексея Быкова выше, но ее можно было бы немного упростить
public sealed class Nothing { public static Nothing AtAll { get { return null; } } }как я не вижу никаких видимых причин, почему ничего.AtAll не мог просто дать null
та же идея (или та, что у Jeppe Stig Nielsen) также отлично подходит для использования с типизированными классами.
например, если тип используется только для описания аргументов процедуры/функции, передаваемых в качестве аргумента некоторому методу, и сам он не принимает никаких аргументов.
(вы все равно нужно либо сделать фиктивную обертку, либо разрешить необязательное "ничего". Но ИМХО использование класса выглядит хорошо с myClass)
void myProcWithNoArguments(Nothing Dummy){ myProcWithNoArguments(){ }или
void myProcWithNoArguments(Nothing Dummy=null){ ... }