Passing a class property as a parameter - c#

I'd like to pass a class property (or a getter/setter if need be) reference to a function.
For example I have an array of a class with lots of boolean flags.
class Flags
{
public bool a;
public bool b;
public bool c;
public string name;
public Flags(bool a, bool b, bool c, string name)
{
this.a = a;
this.b = b;
this.c = c;
this.name = name;
}
}
I can write a method that returns all instances of Flags for which a chosen flag is true
public Flags[] getAllWhereAisTrue(Flags[] array)
{
List<Flags> resultList = new List<Flags>();
for (int i = 0; i < array.Length; i++)
{
if (array[i].a == true) // for each Flags for which a is true
{ // add it to the results list
resultList.Add(array[i]);
}
}
return resultList.ToArray(); //return the results list as an array
}
What would I use to allow me to pass a class property as a parameter, so as to save me from having to write this method once for each boolean property of Flags (in this example that's three times, once for a, b and c)?
I'm trying to avoid giving Flags an array of Booleans in an attempt to keep the resulting code easy to read. I'm writing a library for use by relatively inexperienced coders.
Thank you
(With apologies if this is a dupe of Passing property as parameter in method, I can't quite tell if it's the same issue)

You could use a Func<Flags, bool> as parameter:
public Flags[] getAllWhereAisTrue(Flags[] array, Func<Flags, bool> propertySelector)
{
List<Flags> resultList = new List<Flags>();
for (int i = 0; i < array.Length; i++)
{
if (propertySelector(array[i])) // for each Flags for which a is true
{ // add it to the results list
resultList.Add(array[i]);
}
}
return resultList.ToArray(); //return the results list as an array
}
Then you could use it like this:
var allAFlagsSet = getAllWhereAisTrue(flagsArray, x=> x.a);
But really you should not reinvent this - Linq does this out of the box (notice the similarity):
var allAFlagsSet = flagsArray.Where(x=> x.a).ToArray();
Both solutions would require the a,b,c to be public (should really be a public property in this case)

according to the language spec it is not possible to pass properties as ref parameters. this stackoverflow post is on the same subject. moreover, I'll second the comment of SLaks: LINQ has a method that does just this.

Related

How to check if a place in array is the same object as other object?

I have the following code:
public static bool contains(Team [] ts, Team t)
{
for(int i=0; i<ts.Length; i++)
{
if (ts[i]== t)
{
return true;
}
}
return false;
}
But somehow it always returns false. When I use Equals it throws NullReferenceException and I don't know what else to do.
There are a few points in your question wich are worth discussing.
In order to compare ts[i] and t you are using the equality operator ==. By default, this operator performs a reference equality check between the two operands, put in other words this is equivalent to calling object.ReferenceEquals(ts[i], t). This means that the two operands are considered equal if and only if they are two references to the same memory location.
If this is not the equality semantic that you intend for the class Team, you need to override both the Equals and GetHashCode methods and both the operators == and !=. After that, your code will automatically use the equality semantic that you have defined in your overrides. Start from here if you need more details on this.
The second important point is the one related with the NullReferenceException. If you call t[i].Equals(t) and t[i] is a null reference then you'll get a NullReferenceException. So you have the following choices:
checks whether t[i] is a null reference before calling Equals
use the equality operator instead
use the static method object.Equals instead
Last but not the least, as pointed out in other answers what you are trying to do is already implemented in .NET framework and you should use the already existing Contains extension method.
Notice that when using the already existing Contains extension method you still need to override the equality members of the Team class, as explained above.
As an alternative, you can decide to use this overload of the Contains extension method which allows you to specify the desired equality semantic at the call site, by means of a custom equality comparer (an implementation of IEqualityComparer<Match> in your case). This can be useful if, for any reason, defining several different equality semantics for the Team class (based on the context) makes sense. If you always want to compare Match instances using the same equality semantic, stick with the first choice of overriding the equality members of the class (as explained above) and use the overload of Contains having one parameter only.
It is usually a good way to learn to check how .net framework implemented similiar behaviour in their code.
From .Net Source:
// Contains returns true if the specified element is in the ArrayList.
// It does a linear, O(n) search. Equality is determined by calling
// item.Equals().
//
public virtual bool Contains(Object item) {
if (item==null) {
for(int i=0; i<_size; i++)
if (_items[i]==null)
return true;
return false;
}
else {
for(int i=0; i<_size; i++)
if ( (_items[i] != null) && (_items[i].Equals(item)) )
return true;
return false;
}
}
One way to do this is to create an interface with an Equals method and then the class implement that interface.
With your example:
public interface IEqualable<T>
{
public bool Equal(T t);
}
public class Team : IEqualable<Team>
{
public string TeamName { get; set; }
public bool Equal(Team t2)
{
if(t2 is null) return false;
if (this.TeamName == t2.TeamName)
return true;
return false;
}
}
public class Program
{
static void Main(string[] args)
{
var p = new Team[3] { new Team() { TeamName = "qwe" }, new Team() { TeamName = "asd" }, new Team() { TeamName = "qq" } };
Console.WriteLine(contains(p, new Team { TeamName = "qq" }));
}
public static bool contains(Team[] ts, Team t)
{
for (int i = 0; i < ts.Length; i++)
{
if (ts[i].Equal(t))
{
return true;
}
}
return false;
}
}
More details here

Indexer get by reference or get+set?

This is my class:
class MyArray<T>
{
private T[] data;
public MyArray(int size)
{
data = new T[size];
}
public MyArray(in T[] array)
{
data = new T[array.Length];
for (int i = 0; i < array.Length; i++)
data[i] = array[i];
}
public T this[int i] //I am talking about this indexer
{
get => data[i];
set => data[i] = value;
}
}
Should I, instead of doing like above, define my indexer like this?
public ref T this[int i]
{
get => data[i];
}
Which method should I choose? From what I see, method 1 allows you to execute additional code when getting setting the value, however method 2 allows you to do something like int.TryParse(str, out myArrayObj[i]);
EDIT: This question doesn't only apply to indexers, but to any property in general.
TL;DR If you need a setter then you have to go with regular indexer, because ref properties cannot have setters. If setter is not needed then I would always specify ref keyword in the indexer/property of generic type parameter as they can be value types. It's up to the consumer whether access them by ref or not.
ref keyword does not provide any benefit if the type parameter is reference type (a class), but makes a difference for value types, because they can be accessed directly without being copied. So if you want to have access to original values in your array, you have to use ref keyword. If you want to access value that was in the array, that was passed to MyArray<T> class, then you should not copy the values to other private array, because in this case you will get copies of values in private array.
Following examples show how access by ref differs from regular access:
[Fact]
public void ArrayTest()
{
var structs = new[] {new MyStruct()};
structs[0].Type++;
ref var #struct = ref structs[0];
#struct.Type++;
// Test passes the value was incremented twice, because reference was used.
structs[0].Type.Should().Be(2);
}
[Fact]
public void MyArrayTest()
{
var structs = new MyArray<MyStruct>(new[] {new MyStruct()});
// Compiler error, but was possible in earlier versions of C#
// and would not modify the item in the array,
// because value was copied before modification.
// structs[0].Type++;
var #struct = structs[0];
#struct.Type++;
// Value wasn't incremented, because it was copied on the stack.
structs[0].Type.Should().Be(0);
}
[Fact]
public void MyRefArrayTest()
{
var structs = new MyRefArray<MyStruct>(new[] {new MyStruct()});
structs[0].Type++;
ref var #struct = ref structs[0];
#struct.Type++;
// Test passes the value was incremented twice, because reference was used.
structs[0].Type.Should().Be(2);
}
struct MyStruct
{
public int Type { get; set; }
}
class MyArray<T>
{
private T[] data;
public MyArray(in T[] array)
{
data = new T[array.Length];
Array.Copy(array, data, array.Length);
}
public T this[int i]
{
get => data[i];
set => data[i] = value;
}
}
class MyRefArray<T>
{
private T[] data;
public MyRefArray(in T[] array)
{
data = new T[array.Length];
Array.Copy(array, data, array.Length);
}
public ref T this[int i]
{
get => ref data[i];
// Compiler error, ref indexer cannot have setter.
// set => data[i] = value;
}
}
It depends very much by what you intend to do with it, but I would see it from the encapsulation side:
The classic get set approach is sturdy and robust: everyone using your object will go through YOUR rules when getting or setting any value in the object.
With ref the situation becomes tricky! You're just giving the reference out and the user of the object can do whatever he/she wants with it. It is like giving away your home keys.
You can't protect yourself against users tampering with your private members:
// This might cause several failures or go against the class contract
// and there is no way to check on the value.
public void AbuseRefProperty() => array.Property = null;
The only place I would feel comfortable having a ref property is in a private inner class. There you're sure that no one can tamper with it and the parent class is the only one that has full control.

How to pass a parameter to declare generic type list?

private void listHelper (int listSize, ref Object taker, Object giver, Type type)
{
if (listSize == 0)
{
taker = null;
}
else
{
taker = new List<type>(listSize);
giverType tempGiver;
for (int i = 0; i < listSize; i++)
{
type= new type();
tempGiver.value = giver[i];
taker.Add(tempGiver);
}
}
}
This is my code. I have tried to pass a type parameter to the private method to declare generic type list... But I have no idea what to do.
parameter taker is a list. In this case, taker is storing a generic type of object.
parameter type is a type of the generic.
I have searched about this on the internet for a while. I am still not sure how to do this.
Try making a generic method instead:
private void listHelper<T> (int listSize, out List<T> taker, IList<T> giver)
{
if (listSize == 0)
{
taker = null;
}
else
{
taker = new List<T>(listSize);
for (int i = 0; i < listSize; i++)
{
taker.Add(giver[i]);
}
}
}
Also I suggest using out rather than ref (as I have done) since you always assign a value to taker before returning. This allows the calling code to not have to assign a dummy value before calling your method.
Or better yet, you should just return the List!
private List<T> listHelper<T> (int listSize, IList<T> giver)
{
List<T> taker;
...
return taker;
}
Note, if all your method is doing is copying all elements from giver to taker (that is, specifying listSize is really just a holdover habit from coding C and always equals the number of elements in giver), you can either substitute giver.Count or just do:
private List<T> listHelper<T> (IList<T> giver)
{
return giver.Any() ? giver.ToList() : null;
}
Of course, if listSize is really "number of elements to return, starting at the front of giver", you can do:
private List<T> listHelper<T> (IList<T> giver, int numElements)
{
return giver.Any() ? giver.Take(numElements).ToList() : null;
}
In fact, reading into your question further, it looks like you want to instantiate a new object of some type and set it's value property to the item in giver. So how about this (of course I'm assuming a lot about your taker object and that you have an interface ITaker<U> which specifies a field/property public U value):
private List<T<U>> listHelper<T, U> (IList<U> giver) where T : ITaker<U>, new()
{
return giver.Any() ? giver.Select(g => new T<U>() {value = g}).ToList() : null;
}
I guess its something like:
private void ListHelper<T>(int listSize, ref object taker, object giver)
{
...
List<T> list = new List<T>();
...
}
You should create a Generic method. Generics act as templates in C#. The method is bound when it's declared.
public void ListHelper<T>//...
List<T> my list//...

Is it possible for a function to return two values?

Is it possible for a function to return two values?
Array is possible if the two values are both the same type, but how do you return two different type values?
Can a function return 2 separate values? No, a function in C# can only return a single value.
It is possible though to use other concepts to return 2 values. The first that comes to mind is using a wrapping type such as a Tuple<T1,T2>.
Tuple<int,string> GetValues() {
return Tuple.Create(42,"foo");
}
The Tuple<T1,T2> type is only available in 4.0 and higher. If you are using an earlier version of the framework you can either create your own type or use KeyValuePair<TKey,TValue>.
KeyValuePair<int,string> GetValues() {
return new KeyValuePair<int,sting>(42,"foo");
}
Another method is to use an out parameter (I would highly recomend the tuple approach though).
int GetValues(out string param1) {
param1 = "foo";
return 42;
}
In a word, no.
But you can define a struct (or class, for that matter) for this:
struct TwoParameters {
public double Parameter1 { get; private set; }
public double Parameter2 { get; private set; }
public TwoParameters(double param1, double param2) {
Parameter1 = param1;
Parameter2 = param2;
}
}
This of course is way too specific to a single problem. A more flexible approach would be to define a generic struct like Tuple<T1, T2> (as JaredPar suggested):
struct Tuple<T1, T2> {
public T1 Property1 { get; private set; }
public T2 Property2 { get; private set; }
public Tuple(T1 prop1, T2 prop2) {
Property1 = prop1;
Property2 = prop2;
}
}
(Note that something very much like the above is actually a part of .NET in 4.0 and higher, apparently.)
Then you might have some method that looks like this:
public Tuple<double, int> GetPriceAndVolume() {
double price;
int volume;
// calculate price and volume
return new Tuple<double, int>(price, volume);
}
And code like this:
var priceAndVolume = GetPriceAndVolume();
double price = priceAndVolume.Property1;
int volume = priceAndVolume.Property2;
It is not directly possible. You need to return a single parameter that wraps the two parameters, or use out parameters:
object Method(out object secondResult)
{
//...
Or:
KeyValuePair<object,object> Method()
{
// ..
All of the possible solutions miss one major point; why do you want to return two values from a method? The way I see it, there are two possible cases; a) you are returning two values that really should be encapsulated in one object (e.g. height and width of something, so you should return an object that represents that something) or b) this is a code smell and you really need to think about why the method is returning two values (e.g. the method is really doing two things).
with C# 7, you can now return a ValueTuple:
static (bool success, string value) GetValue(string key)
{
if (!_dic.TryGetValue(key, out string v)) return (false, null);
return (true, v); // this is a ValueType literal
}
static void Main(string[] args)
{
var (s, v) = GetValue("foo"); // (s, v) desconstructs the returned tuple
if (s) Console.WriteLine($"foo: {v}");
}
ValueTuple is a value-type, which makes it a great choice for a return value compared with a reference-type Tuple - no object needs to be garbage-collected.
Also, note that you can give a name to the values returned. It is really nice.
For that reason alone I wish it was possible to declare a ValueTuple with only one element. Alas, it is not allowed:
static (string error) Foo()
{
// ... does not work: ValueTuple must contain at least two elements
}
Not directly. Your options are either to return some kind of custom struct or class with multiple properties, use KeyValuePair if you simply want to return two values, or use out parameters.
You have basically (at least) two options, either you make an out parameter in addition to the return value of the function, something like T1 Function(out T2 second) or you make your own class putting these two types together, something like a Pair<T1,T2>. I personally prefer the second way but it's your choice.
In C# you can return more than one value using an out parameter. See example in the TryParse method of Int32 struct. It returns bool and an integer in an out parameter.
no but you can use an out parameter
int whatitis;
string stuff = DoStuff(5, out whatitis);
public string DoStuff(int inParam, out int outParam)
{
outParam = inParam + 10;
return "donestuff";
}
It is not possible to return more than one value from a function, unless you are returning a type that contains multiple values in it (Struct, Dictionary, etc). The only other way would be to use the "out" or "ref" keywords on the incoming parameters.
You could use the out parameter.
int maxAge;
int minAge;
public int GetMaxAgeAndMinAge(out int maxAge, out int minAge)
{
MaxAge = 60;
MinAge = 0;
return 1; //irrelevant for this example since we care about the values we pass in
}
I really tend to stay away from this, I think that it is a code-smell. It works for quick and dirty though. A more testable and better approach would be to pass an object that represents your domain (the need to see two these two values).
you can try this
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
To return 2 values I usually use Pair class from http://blog.o-x-t.com/2007/07/16/generic-pair-net-class/.
If you need to return from method 2 values that describe the range, e.g. From/To or Min/Max, you can use FromToRange class.
public class FromToRange<T>
{
public T From { get; set; }
public T To { get; set; }
public FromToRange()
{
}
public FromToRange(T from, T to)
{
this.From = from;
this.To = to;
}
public override string ToString()
{
string sRet = String.Format("From {0} to {1}", From, To);
return sRet;
}
public override bool Equals(object obj)
{
if (this == obj) return true;
FromToRange<T> pair = obj as FromToRange<T>;
if (pair == null) return false;
return Equals(From, pair.From) && Equals(To, pair.To);
}
public override int GetHashCode()
{
return (From != null ? From.GetHashCode() : 0) + 29 * (To != null ? To.GetHashCode() : 0);
}
}

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