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){ ... }