C#: Less ugly syntax for creating delegate lists? - c#

I'm building a system a bit like LINQ, and in doing it, am trying to support polymorphic callback handler lists, and am running into several kinds of problems. The short way to ask my question is to just show you some code. My new system supports "Groups" and groups have a vector of entry points (below, UPDATE and CHECKPT) and each element on the vector is a polymorphic list of delegates, which I'll call back using reflection.
So, sample code:
namespace ConsoleApplication1
{
internal delegate void GroupISDHandler(int i, string s, double d);
class Group
{
public class myHandlers {
internal List<Delegate> hList = new List<Delegate>();
public static myHandlers operator +(myHandlers a, Delegate b) {
a.hList.Add(b);
return a;
}
}
public class mimicVector {
public List<myHandlers> ListofhLists = new List<myHandlers>();
public myHandlers this[int i] { get { return ListofhLists[i]; } set { ListofhLists[i] = value; } }
}
public mimicVector handlers = new mimicVector();
public Group(string name) { ... }
}
class Program
{
internal const int UPDATE = 0;
internal const int CHECKPT = 1;
public static void Main()
{
Group g = new Group("group name");
g.handlers[UPDATE] += (GroupISDHandler)delegate(int x, string s, double d) {
Console.WriteLine("my int,string,double handler was called, with x = {0}, s = {1}, d = {2}",
x,s,d);
};
}
}
}
My questions centers on the registration line. Why can't C# infer the types so that I could omit the cast and the new delegate type entirely? I would think that from
g.handlers[UPDATE] += delegate(int x, string s, double d) {
Console.WriteLine(....);
};
C# could infer the needed type signature. delegate() would be a kind of anonymous type and C# would just generate something like
private delegate void _atype1(int _a0, string _a1, double _a2)
and then insert (Delegate)(_atype1) before compiling the line. Thus my user won't need to declare a delegate type (which currently forces her to type the argument list twice, in effect).
I do have System.Linq since I'm on VS 2010. So if LINQ can somehow infer the needed casts...

you should be able to do it this way:
g.handlers[UPDATE] += (GroupISDHandler)((x, s, d) =>
Console.WriteLine(
"my int,string,double handler was called, with x = {0}, s = {1}, d = {2}",
x, s, d));
another option would be:
have a class named ´Parameters´ that is a container for whatever the user can send, might be defined types if they never change, or a list of objects if you pretend to send and receive different amount of parameters. Then instead of a Delegate, you would take Action that equals a delegate that takes one argument, and you could do your call without casting like this:
p => Console.WriteLine("x = {0}, s = {1}, d = {2}", p.x, p.s, p.d);

Turns out that the answer is basically this: while you can do the inference in the kinds of situations I had in mind, the C# owners want completely general solutions and polymorphism makes the type inference problem too hard to solve in a sufficiently general way, in their view. I myself disagree since I end up typing all my type signatures twice, but that's their reasoning.

Related

How To Define A Flexible delegate field with multiple optional parameters?

I'm developing a simulation game where I have some conditional methods in various classes which I want to use them for random in-game events.
My aim is creating a user-friendly event class where users can add events via XML serializing (that part is good to go). So I'm trying to keep things simple and generic as much as possible. I got some conditional methods in various classes like
public class Person
{
static bool IsOlderThan(int age) {/*...*/}
}
public class Faction
{
static bool HasRelationMoreThan(Faction faction,float value) {/*...*/}
}
and so on...
I must define a Func<> parameter or another delegate which can accept these methods with different scope of parameters, instead of defining a different field for every single one of them. TL;DR: I need a delegate type which accepts any method as value.
Is there any way to create a flexible, generic method reference like this?
Take a look at the MulticastDelegate class. It's a base class for all delegates.
But be careful. MulticastDelegates are invoked via DynamicInvoke(), which works slower than Invoke(). And you also have to control number and types of parameters passed into DynamicInvoke() because it can cause runtime errors.
private void TestMulticastDelegate()
{
Func<int, bool> function1 = IntToBool;
Func<string, bool> function2 = StringToBool;
Func<int, string, bool> function3 = IntAndStringToBool;
int intArg = 1;
string stringArg = "someString";
MulticastDelegate d;
d = new Func<int, bool>(IntToBool);
bool res1 = d.DynamicInvoke(intArg).Equals(function1(intArg)); // always true
d = new Func<string, bool>(StringToBool);
bool res2 = d.DynamicInvoke(stringArg).Equals(function2(stringArg)); // always true
d = new Func<int, string, bool>(IntAndStringToBool);
bool res3 = d.DynamicInvoke(intArg, stringArg).Equals(function3(intArg, stringArg)); // always true
}
private bool IntToBool(int i)
{
return i == 0;
}
private bool StringToBool(string s)
{
return string.IsNullOrEmpty(s);
}
private bool IntAndStringToBool(int i, string s)
{
return i.ToString().Equals(s, StringComparison.OrdinalIgnoreCase);
}

How to reduce repetition for this case?

In C# I have two classes of the form A, A where A is a customised IEnumerable over reference types and B, C are reference types that inherit from a class D. There is a property named P that exists on B, C but not D, and it would be inappropriate to add it to D as other classes inheriting from D shouldn't have P. I have instances b, c of A, A for which I need to do the following for constants x, y of the same type as P:
b.Where(v => v.P == x).ForEach(v => v.P = y);
c.Where(v => v.P == x).ForEach(v => v.P = y);
This code works, but how can I avoid repetition viz. the DRY principle?
My own efforts have encountered three major difficulties:
Since P doesn't exist on D one cannot simply create a function that works on instances of D and cast viz. b.Select(v => (D)v).
Since P doesn't exist on generic types, the compiler won't tolerate the obvious way to run this logic with a generic T.
Since A only takes T where class, a generic using A complains that T needs to be a reference type.
I'm especially interested in solutions that create a generic method on a new interface from which B, C can inherit, as I've been advised this approach should be possible.
In my opinion you want to solve a problem which doesn't exist. It will be much simpler with your class definition, but you can do something like this:
class Program
{
static void Main(string[] args)
{
int x = 1;
int y = 2;
var b = new MyCustomList<B>();
b.Foo(v => v.P == x, n => n.P = y);
}
}
public static class Extensions
{
public static void Foo<T>(this IFoo<T> #this, Func<T, bool> predicate, Action<T> action) => #this.Where(predicate).ToList().ForEach(action);
}
public interface IFoo<T> : IList<T> { }
class MyCustomList<T> : List<T>, IFoo<T> { }
class B
{
public int P { get; set; }
}
If I'm understanding you correctly, you want something similar to this:
public interface IHasPropertyP { Foo P { get; } }
public class B: D, IHasPropertyP { ... }
public class C: D, IHasPropertyP { ... }
List<D> dees = ... //I don't care if the type of the items is B, C or D
var onlyThoseWhoHavePropertyP = dees.OfType<IHasPropertyP>();
onlyThoseWhoHavePropertyP.Where(v => v.P == x).{whatever needs to be done...}
This code works, but how can I avoid repetition viz. the DRY principle?
You can remove this repetition - there are at least two ways I can think of - but consider what it gains you here. The operation you want to carry out is "Set P to Y on those objects where it is X" - this is about as simple as it gets, and having two parallel lines next to each other makes it completely clear in a way that a DRYer solution doesn't.
The two ways I can think of have been covered in other answers, but briefly:
create a common interface IHaveAPropertyP which B and C are then made to implement. Requires a code change on B and C
have a method that is passed an object of arbitrary type, along with methods for getting and seting a property P on objects of that type.
Either way, there will still be two very similar lines of code next to each other - given this, why complicate matters?

C# cast generic type (like C++ user defined conversions)

Is there a way in C# to perform a user defined conversion for generic types ?
for example:
class Stack<T>
{
private T x; //should be an array but doesn't matter for this example
public Stack(T input)
{
x = input;
}
public Stack<Q> Convert<Q>(Stack<T> inputStack)
{
//what would go here ? The call is below.
}
}
//main code
Stack<int> stack = new Stack<int>(2);
Stack<long> longstack = stack.Convert<long>(stack);
I would imagine that the compiler can deduce that Q is long and T is int in the Convert function, but it doesn't seem to work.
No, because class-level generic type parameters can't be auto-infered from usage.
I would imagine that the compiler can deduce that Q is long and T is
int in the Convert function, but it doesn't seem to work.
Maybe, but at the end of the day, a generic type parameter doesn't belong to constructor. That is, you provide a generic argument to the type based on what constructor parameter/argument? What happens if there're more than a constructor parameter?
public class A<T>
{
// Which one should be used to auto-infer T from usage?
// Maybe the integer? Or the bool? Or just the string...?
// Every choice seems a joke, because it would be absolutely
// arbitrary and unpredictable...
public A(int x, string y, bool z)
{
}
}
Now take your sample code as example. It has the same issue: what argument should be used from your Convert static method to infer generic type argument from usage? What happens if Convert has more than an argument...?
Here is extension method for standart Stack class (you can rewrite it a little and use like instance method in your own Stack class):
public static class MyStackExtensions
{
public static Stack<TDest> Convert<TSrc, TDest>(
this Stack<TSrc> stack,
Func<TSrc, TDest> converter = null)
{
if (stack == null)
throw new ArgumentNullException("stack");
var items = converter == null
? stack.Select(i => (TDest) System.Convert.ChangeType(i, typeof (TDest)))
: stack.Select(converter);
return new Stack<TDest>(items.Reverse());
}
}
Convert stack from int to long using convert function - no type params needed :-)
var intStack = new Stack<int>(new[] { 1, 2, 3 });
var longStack = intStack.Convert(i => (long)i);
Or using standart conversion:
var intStack = new Stack<int>(new[] { 1, 2, 3 });
var longStack = intStack.Convert<int, long>();

Why do some C# lambda expressions compile to static methods?

As you can see in the code below, I have declared an Action<> object as a variable.
Would anybody please let me know why this action method delegate behaves like a static method?
Why does it return true in the following code?
Code:
public static void Main(string[] args)
{
Action<string> actionMethod = s => { Console.WriteLine("My Name is " + s); };
Console.WriteLine(actionMethod.Method.IsStatic);
Console.Read();
}
Output:
This is most likely because there are no closures, for example:
int age = 25;
Action<string> withClosure = s => Console.WriteLine("My name is {0} and I am {1} years old", s, age);
Action<string> withoutClosure = s => Console.WriteLine("My name is {0}", s);
Console.WriteLine(withClosure.Method.IsStatic);
Console.WriteLine(withoutClosure.Method.IsStatic);
This will output false for withClosure and true for withoutClosure.
When you use a lambda expression, the compiler creates a little class to contain your method, this would compile to something like the following (the actual implementation most likely varies slightly):
private class <Main>b__0
{
public int age;
public void withClosure(string s)
{
Console.WriteLine("My name is {0} and I am {1} years old", s, age)
}
}
private static class <Main>b__1
{
public static void withoutClosure(string s)
{
Console.WriteLine("My name is {0}", s)
}
}
public static void Main()
{
var b__0 = new <Main>b__0();
b__0.age = 25;
Action<string> withClosure = b__0.withClosure;
Action<string> withoutClosure = <Main>b__1.withoutClosure;
Console.WriteLine(withClosure.Method.IsStatic);
Console.WriteLine(withoutClosure.Method.IsStatic);
}
You can see the resulting Action<string> instances actually point to methods on these generated classes.
The "action method" is static only as a side effect of the implementation. This is a case of an anonymous method with no captured variables. Since there are no captured variables, the method has no additional lifetime requirements beyond those for local variables in general. If it did reference other local variables, its lifetime extends to the lifetime of those other variables (see sec. L.1.7, Local variables, and sec. N.15.5.1, Captured outer variables, in the C# 5.0 specification).
Note that the C# specification only talks about anonymous methods being converted to "expression trees", not "anonymous classes". While the expression tree could be represented as additional C# classes, for example, in the Microsoft compiler, this implementation is not required (as acknowledged by sec. M.5.3 in the C# 5.0 specification). Therefore, it is undefined whether the anonymous function is static or not. Moreover, section K.6 leaves much open as to the details of expression trees.
Delegate caching behavior was changed in Roslyn. Previously, as stated, any lambda expression which didn't capture variables was compiled into a static method at the call site. Roslyn changed this behavior. Now, any lambda, which captures variables or not, is transformed into a display class:
Given this example:
public class C
{
public void M()
{
var x = 5;
Action<int> action = y => Console.WriteLine(y);
}
}
Native compiler output:
public class C
{
[CompilerGenerated]
private static Action<int> CS$<>9__CachedAnonymousMethodDelegate1;
public void M()
{
if (C.CS$<>9__CachedAnonymousMethodDelegate1 == null)
{
C.CS$<>9__CachedAnonymousMethodDelegate1 = new Action<int>(C.<M>b__0);
}
Action<int> arg_1D_0 = C.CS$<>9__CachedAnonymousMethodDelegate1;
}
[CompilerGenerated]
private static void <M>b__0(int y)
{
Console.WriteLine(y);
}
}
Roslyn:
public class C
{
[CompilerGenerated]
private sealed class <>c__DisplayClass0
{
public static readonly C.<>c__DisplayClass0 CS$<>9__inst;
public static Action<int> CS$<>9__CachedAnonymousMethodDelegate2;
static <>c__DisplayClass0()
{
// Note: this type is marked as 'beforefieldinit'.
C.<>c__DisplayClass0.CS$<>9__inst = new C.<>c__DisplayClass0();
}
internal void <M>b__1(int y)
{
Console.WriteLine(y);
}
}
public void M()
{
Action<int> arg_22_0;
if (arg_22_0 = C.
<>c__DisplayClass0.CS$<>9__CachedAnonymousMethodDelegate2 == null)
{
C.<>c__DisplayClass0.CS$<>9__CachedAnonymousMethodDelegate2 =
new Action<int>(C.<>c__DisplayClass0.CS$<>9__inst.<M>b__1);
}
}
}
Delegate caching behavior changes in Roslyn talks about why this change was made.
As of C# 6, this will always default to instance methods now, and will never be static (so actionMethod.Method.IsStatic will always be false).
See here: Why has a lambda with no capture changed from a static in C# 5 to an instance method in C# 6?
and here: Difference in CSC and Roslyn compiler's static lambda expression evaluation?
The method has no closures and also references a static method itself (Console.WriteLine), so I would expect it to be static. The method will declare an enclosing anonymous type for a closure, but in this instance it is not required.

Return multiple values to a method caller

I read the C++ version of this question but didn't really understand it.
Can someone please explain clearly if it can be done in C#, and how?
In C# 7 and above, see this answer.
In previous versions, you can use .NET 4.0+'s Tuple:
For Example:
public Tuple<int, int> GetMultipleValue()
{
return Tuple.Create(1,2);
}
Tuples with two values have Item1 and Item2 as properties.
Now that C# 7 has been released, you can use the new included Tuples syntax
(string, string, string) LookupName(long id) // tuple return type
{
... // retrieve first, middle and last from data storage
return (first, middle, last); // tuple literal
}
which could then be used like this:
var names = LookupName(id);
WriteLine($"found {names.Item1} {names.Item3}.");
You can also provide names to your elements (so they are not "Item1", "Item2" etc). You can do it by adding a name to the signature or the return methods:
(string first, string middle, string last) LookupName(long id) // tuple elements have names
or
return (first: first, middle: middle, last: last); // named tuple elements in a literal
They can also be deconstructed, which is a pretty nice new feature:
(string first, string middle, string last) = LookupName(id1); // deconstructing declaration
Check out this link to see more examples on what can be done :)
You can use three different ways
1. ref / out parameters
using ref:
static void Main(string[] args)
{
int a = 10;
int b = 20;
int add = 0;
int multiply = 0;
Add_Multiply(a, b, ref add, ref multiply);
Console.WriteLine(add);
Console.WriteLine(multiply);
}
private static void Add_Multiply(int a, int b, ref int add, ref int multiply)
{
add = a + b;
multiply = a * b;
}
using out:
static void Main(string[] args)
{
int a = 10;
int b = 20;
int add;
int multiply;
Add_Multiply(a, b, out add, out multiply);
Console.WriteLine(add);
Console.WriteLine(multiply);
}
private static void Add_Multiply(int a, int b, out int add, out int multiply)
{
add = a + b;
multiply = a * b;
}
2. struct / class
using struct:
struct Result
{
public int add;
public int multiply;
}
static void Main(string[] args)
{
int a = 10;
int b = 20;
var result = Add_Multiply(a, b);
Console.WriteLine(result.add);
Console.WriteLine(result.multiply);
}
private static Result Add_Multiply(int a, int b)
{
var result = new Result
{
add = a * b,
multiply = a + b
};
return result;
}
using class:
class Result
{
public int add;
public int multiply;
}
static void Main(string[] args)
{
int a = 10;
int b = 20;
var result = Add_Multiply(a, b);
Console.WriteLine(result.add);
Console.WriteLine(result.multiply);
}
private static Result Add_Multiply(int a, int b)
{
var result = new Result
{
add = a * b,
multiply = a + b
};
return result;
}
3. Tuple
Tuple class
static void Main(string[] args)
{
int a = 10;
int b = 20;
var result = Add_Multiply(a, b);
Console.WriteLine(result.Item1);
Console.WriteLine(result.Item2);
}
private static Tuple<int, int> Add_Multiply(int a, int b)
{
var tuple = new Tuple<int, int>(a + b, a * b);
return tuple;
}
C# 7 Tuples
static void Main(string[] args)
{
int a = 10;
int b = 20;
(int a_plus_b, int a_mult_b) = Add_Multiply(a, b);
Console.WriteLine(a_plus_b);
Console.WriteLine(a_mult_b);
}
private static (int a_plus_b, int a_mult_b) Add_Multiply(int a, int b)
{
return(a + b, a * b);
}
You cannot do this in C#. What you can do is have a out parameter or return your own class (or struct if you want it to be immutable).
Using out parameter
public int GetDay(DateTime date, out string name)
{
// ...
}
Using custom class (or struct)
public DayOfWeek GetDay(DateTime date)
{
// ...
}
public class DayOfWeek
{
public int Day { get; set; }
public string Name { get; set; }
}
In C#7 There is a new Tuple syntax:
static (string foo, int bar) GetTuple()
{
return ("hello", 5);
}
You can return this as a record:
var result = GetTuple();
var foo = result.foo
// foo == "hello"
You can also use the new deconstructor syntax:
(string foo) = GetTuple();
// foo == "hello"
Be careful with serialisation however, all this is syntactic sugar - in the actual compiled code this will be a Tuple<string, int> (as per the accepted answer) with Item1 and Item2 instead of foo and bar. That means that serialisation (or deserialisation) will use those property names instead.
So, for serialisation declare a record class and return that instead.
Also new in C#7 is an improved syntax for out parameters. You can now declare the out inline, which is better suited in some contexts:
if(int.TryParse("123", out int result)) {
// Do something with result
}
However, mostly you'll use this in .NET's own libraries, rather than in you own functions.
If you mean returning multiple values, you can either return a class/struct containing the values you want to return, or use the "out" keyword on your parameters, like so:
public void Foo(int input, out int output1, out string output2, out string errors) {
// set out parameters inside function
}
There is many way; but if you don't want to create a new Object or structure or something like this you can do like below after C# 7.0 :
(string firstName, string lastName) GetName(string myParameter)
{
var firstName = myParameter;
var lastName = myParameter + " something";
return (firstName, lastName);
}
void DoSomethingWithNames()
{
var (firstName, lastName) = GetName("myname");
}
Previous poster is right. You cannot return multiple values from a C# method. However, you do have a couple of options:
Return a structure that contains multiple members
Return an instance of a class
Use output parameters (using the out or ref keywords)
Use a dictionary or key-value pair as output
The pros and cons here are often hard to figure out. If you return a structure, make sure it's small because structs are value type and passed on the stack. If you return an instance of a class, there are some design patterns here that you might want to use to avoid causing problems - members of classes can be modified because C# passes objects by reference (you don't have ByVal like you did in VB).
Finally you can use output parameters but I would limit the use of this to scenarios when you only have a couple (like 3 or less) of parameters - otherwise things get ugly and hard to maintain. Also, the use of output parameters can be an inhibitor to agility because your method signature will have to change every time you need to add something to the return value whereas returning a struct or class instance you can add members without modifying the method signature.
From an architectural standpoint I would recommend against using key-value pairs or dictionaries. I find this style of coding requires "secret knowledge" in code that consumes the method. It must know ahead of time what the keys are going to be and what the values mean and if the developer working on the internal implementation changes the way the dictionary or KVP is created, it could easily create a failure cascade throughout the entire application.
You either return a class instance or use out parameters. Here's an example of out parameters:
void mymethod(out int param1, out int param2)
{
param1 = 10;
param2 = 20;
}
Call it like this:
int i, j;
mymethod(out i, out j);
// i will be 20 and j will be 10
Some answers suggest using out parameters but I recommend
not using this due to they don’t work with async methods. See
this for more information.
Other answers stated using Tuple, which I would recommend too but using the new feature introduced in C# 7.0.
(string, string, string) LookupName(long id) // tuple return type
{
... // retrieve first, middle and last from data storage
return (first, middle, last); // tuple literal
}
var names = LookupName(id);
WriteLine($"found {names.Item1} {names.Item3}.");
Further information can be found here.
<--Return more statements like this you can -->
public (int,string,etc) Sample( int a, int b)
{
//your code;
return (a,b);
}
You can receive code like
(c,d,etc) = Sample( 1,2);
I hope it works.
No, you can't return multiple values from a function in C# (for versions lower than C# 7), at least not in the way you can do it in Python.
However, there are a couple alternatives:
You can return an array of type object with the multiple values you want in it.
private object[] DoSomething()
{
return new [] { 'value1', 'value2', 3 };
}
You can use out parameters.
private string DoSomething(out string outparam1, out int outparam2)
{
outparam1 = 'value2';
outparam2 = 3;
return 'value1';
}
There are several ways to do this. You can use ref parameters:
int Foo(ref Bar bar) { }
This passes a reference to the function thereby allowing the function to modify the object in the calling code's stack. While this is not technically a "returned" value it is a way to have a function do something similar. In the code above the function would return an int and (potentially) modify bar.
Another similar approach is to use an out parameter. An out parameter is identical to a ref parameter with an additional, compiler enforced rule. This rule is that if you pass an out parameter into a function, that function is required to set its value prior to returning. Besides that rule, an out parameter works just like a ref parameter.
The final approach (and the best in most cases) is to create a type that encapsulates both values and allow the function to return that:
class FooBar
{
public int i { get; set; }
public Bar b { get; set; }
}
FooBar Foo(Bar bar) { }
This final approach is simpler and easier to read and understand.
In C# 4, you will be able to use built-in support for tuples to handle this easily.
In the meantime, there are two options.
First, you can use ref or out parameters to assign values to your parameters, which get passed back to the calling routine.
This looks like:
void myFunction(ref int setMe, out int youMustSetMe);
Second, you can wrap up your return values into a structure or class, and pass them back as members of that structure. KeyValuePair works well for 2 - for more than 2 you would need a custom class or struct.
you can try this "KeyValuePair"
private KeyValuePair<int, int> GetNumbers()
{
return new KeyValuePair<int, int>(1, 2);
}
var numbers = GetNumbers();
Console.WriteLine("Output : {0}, {1}",numbers.Key, numbers.Value);
Output :
Output : 1, 2
Classes, Structures, Collections and Arrays can contain multiple values. Output and reference parameters can also be set in a function. Return multiple values is possible in dynamic and functional languages by means of tuples, but not in C#.
When your method is async and you want to return multiple properties. You must do like this:
public async Task<(int, int)> GetMultipleValues(){
return (1,2);
}
Mainly two methods are there.
1. Use out/ref parameters
2. Return an Array of objects
Here are basic Two methods:
1) Use of 'out' as parameter
You can use 'out' for both 4.0 and minor versions too.
Example of 'out':
using System;
namespace out_parameter
{
class Program
{
//Accept two input parameter and returns two out value
public static void rect(int len, int width, out int area, out int perimeter)
{
area = len * width;
perimeter = 2 * (len + width);
}
static void Main(string[] args)
{
int area, perimeter;
// passing two parameter and getting two returning value
Program.rect(5, 4, out area, out perimeter);
Console.WriteLine("Area of Rectangle is {0}\t",area);
Console.WriteLine("Perimeter of Rectangle is {0}\t", perimeter);
Console.ReadLine();
}
}
}
Output:
Area of Rectangle is 20
Perimeter of Rectangle is 18
*Note:*The out-keyword describes parameters whose actual variable locations are copied onto the stack of the called method, where those same locations can be rewritten. This means that the calling method will access the changed parameter.
2) Tuple<T>
Example of Tuple:
Returning Multiple DataType values using Tuple<T>
using System;
class Program
{
static void Main()
{
// Create four-item tuple; use var implicit type.
var tuple = new Tuple<string, string[], int, int[]>("perl",
new string[] { "java", "c#" },
1,
new int[] { 2, 3 });
// Pass tuple as argument.
M(tuple);
}
static void M(Tuple<string, string[], int, int[]> tuple)
{
// Evaluate the tuple's items.
Console.WriteLine(tuple.Item1);
foreach (string value in tuple.Item2)
{
Console.WriteLine(value);
}
Console.WriteLine(tuple.Item3);
foreach (int value in tuple.Item4)
{
Console.WriteLine(value);
}
}
}
Output
perl
java
c#
1
2
3
NOTE: Use of Tuple is valid from Framework 4.0 and above.Tuple type is a class. It will be allocated in a separate location on the managed heap in memory. Once you create the Tuple, you cannot change the values of its fields. This makes the Tuple more like a struct.
A method taking a delegate can provide multiple values to the caller. This borrows from my answer here and uses a little bit from Hadas's accepted answer.
delegate void ValuesDelegate(int upVotes, int comments);
void GetMultipleValues(ValuesDelegate callback)
{
callback(1, 2);
}
Callers provide a lambda (or a named function) and intellisense helps by copying the variable names from the delegate.
GetMultipleValues((upVotes, comments) =>
{
Console.WriteLine($"This post has {upVotes} Up Votes and {comments} Comments.");
});
From this article, you can use three options as posts above said.
KeyValuePair is quickest way.
out is at the second.
Tuple is the slowest.
Anyway, this is depend on what is the best for your scenario.
Future version of C# is going to include named tuples.
Have a look at this channel9 session for the demo
https://channel9.msdn.com/Events/Build/2016/B889
Skip to 13:00 for the tuple stuff. This will allow stuff like:
(int sum, int count) Tally(IEnumerable<int> list)
{
// calculate stuff here
return (0,0)
}
int resultsum = Tally(numbers).sum
(incomplete example from video)
Just use in OOP manner a class like this:
class div
{
public int remainder;
public int quotient(int dividend, int divisor)
{
remainder = ...;
return ...;
}
}
The function member returns the quotient which most callers are primarily interested in. Additionally it stores the remainder as a data member, which is easily accessible by the caller afterwards.
This way you can have many additional "return values", very useful if you implement database or networking calls, where lots of error messages may be needed but only in case an error occurs.
I entered this solution also in the C++ question that OP is referring to.
You could use a dynamic object. I think it has better readability than Tuple.
static void Main(string[] args){
var obj = GetMultipleValues();
Console.WriteLine(obj.Id);
Console.WriteLine(obj.Name);
}
private static dynamic GetMultipleValues() {
dynamic temp = new System.Dynamic.ExpandoObject();
temp.Id = 123;
temp.Name = "Lorem Ipsum";
return temp;
}
Ways to do it:
1) KeyValuePair (Best Performance - 0.32 ns):
KeyValuePair<int, int> Location(int p_1, int p_2, int p_3, int p_4)
{
return new KeyValuePair<int,int>(p_2 - p_1, p_4-p_3);
}
2) Tuple - 5.40 ns:
Tuple<int, int> Location(int p_1, int p_2, int p_3, int p_4)
{
return new Tuple<int, int>(p_2 - p_1, p_4-p_3);
}
3) out (1.64 ns) or ref
4) Create your own custom class/struct
ns -> nanoseconds
Reference: multiple-return-values.
You can also use an OperationResult
public OperationResult DoesSomething(int number1, int number2)
{
// Your Code
var returnValue1 = "return Value 1";
var returnValue2 = "return Value 2";
var operationResult = new OperationResult(returnValue1, returnValue2);
return operationResult;
}
As an alternative you could set your method to void and not return anything. Instead create a public class with parameters and set them inside your method.
public class FooBar()
{
public string foo { get; set; }
public int bar { get; set; }
}
Then for your method try this
public void MyMethod(Foo foo, Bar bar)
{
FooBar fooBar = new FooBar();
fooBar.foo = "some string";
fooBar.bar = 1;
}
you can try this
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}

Categories