Indexer get by reference or get+set? - c#

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.

Related

Is there a workaround to use static methods by a generic class?

I have a rather simple problem, but there seems to be no solution within C#.
I have around 100 Foo classes where each implement a static FromBytes() method. There are also some generic classes which shall use these methods for its own FromBytes(). BUT the generic classes cannot use the static FromBytes() methods, because T.FromBytes(...) is illegal.
Do I miss something or is there no way to implement this functionality?
public class Foo1
{
public static Foo1 FromBytes(byte[] bytes, ref int index)
{
// build Foo1 instance
return new Foo1()
{
Property1 = bytes[index++],
Property2 = bytes[index++],
// [...]
Property10 = bytes[index++]
};
}
public int Property1 { get; set; }
public int Property2 { get; set; }
// [...]
public int Property10 { get; set; }
}
//public class Foo2 { ... }
// [...]
//public class Foo100 { ... }
// Generic class which needs the static method of T to work
public class ListOfFoo<T> : System.Collections.Generic.List<T>
{
public static ListOfFoo<T> FromBytes(byte[] bytes, ref int index)
{
var count = bytes[index++];
var listOfFoo = new ListOfFoo<T>();
for (var i = 0; i < count; i++)
{
listOfFoo.Add(T.FromBytes(bytes, ref index)); // T.FromBytes(...) is illegal
}
return listOfFoo;
}
}
I think it would be unfair to choose an answer as accepted answer, after all answers and comments have contributed in different ways with their different views. It would be nice if someone writes a good overview about the different approaches with their pros and cons. That should be accepted after it helps future developers best.
The best option would be to simply accept the specific FromBytes function as a delegate to your generic FromBytes function. This avoids both the performance cost and lack of compile time verifiability that comes along with using reflection.
public delegate T FromBytesFunc<T>(byte[] bytes, ref int index);
public static List<T> FromBytes<T>(byte[] bytes, ref int index,
FromBytesFunc<T> function)
{
var count = bytes[index++];
var listOfFoo = new List<T>();
for (var i = 0; i < count; i++)
{
listOfFoo.Add(function(bytes, ref index));
}
return listOfFoo;
}
Note that if you make the method, rather than the class it's in, generic, you can get the compiler to infer the generic argument. It could be called like so:
var list = SomeClass.FromBytes(bytes, ref index, Foo1.FromBytes);
The problem is that you're trying to use FromBytes as an extension method when it's not. From what I gather, you're trying to call the appropriate FromBytes for whatever <T> is, as defined in whatever class you've already created for T.
What you need to do is call the method via reflection.
Try looking at some of these threads for help on how to accomplish this.
Use Reflection to call generic method on object instance with signature: SomeObject.SomeGenericInstanceMethod<T>(T argument)
How do I use reflection to call a generic method?
Calling generic method using reflection in .NET
How to call generic method with a given Type object?
Could you just implement the static FromBytes method generically in a utility class? Then do something like this?
listOf.Add(Utility.FromBytes<T>(bytes, ref index));
That utility method might be a bit ugly if each methods FromBytes is a lot different, but it wouldn't be too bad, it's all code that used to live in each class anyway.
Something like this:
public static class Utility
{
public static T FromBytes<T>(byte[] bytes, ref int index)
{
if (typeof(T) is Foo1)
{
return Foo1.GetBytes(bytes, ref index);
}
//etc....
}
}
You could also hide that reflection code here as pointed out by other answers. Unfortunately there doesn't seem to be a very clean way to do this, but hiding the messy stuff in a utility method may be the best option.
You can use reflection to find the method on that type and then build a delegate for it. Something like:
delegate T FromBytesFunc<T>(byte[] bytes, ref int index);
public static ListOfFoo<T> FromBytes(byte[] bytes, ref int index)
{
FromBytesFunc<T> fromBytes =
(FromBytesFunc<T>)Delegate.CreateDelegate(
typeof(FromBytesFunc<T>), typeof(T).GetMethod("FromBytes")
var count = bytes[index++];
var listOf = new ListOfFoo<T>();
for (var i = 0; i < count; i++)
{
listOf.Add(fromBytes(bytes, ref index));
}
return listOf;
}
You can try something like this:
sealed class RetType
{
public object Value
{
get;
private set;
}
public int Index
{
get;
private set;
}
public RetType(object value, int index)
{
Value = value;
Index = index;
}
}
public class ListOfFoo<T> : System.Collections.Generic.List<T>
{
static readonly Dictionary<Type, Func<byte[], int, RetType>> dic = new Dictionary<Type, Func<byte[], int, RetType>>
{
{
typeof(Foo1),
new Func<byte[], int, RetType>((bytes, index) =>
{
var value = Foo1.FromBytes(bytes, ref index);
return new RetType(value, index);
})
}
// add here others Foo
};
public static ListOfFoo<T> FromBytes(byte[] bytes, ref int index)
{
var count = bytes[index++];
var listOf = new ListOfFoo<T>();
for (var i = 0; i < count; i++)
{
var o = dic[typeof(T)](bytes, index);
listOf.Add((T)o.Value);
index = o.Index;
}
return listOf;
}
}
You build a lookup to finde the method you want to call to build the instance.
Not sure if this works for you, but it is an option:
Define an interface IHaveFromBytesMethod<T> which defines a FromBytes(...) instance method.
Make all Foo# types implement this interface. (If you do not want this instance method to be visible immediately, you could implement the interface explicitly.)
All implementations of the instance method simply forward the call to the static method of that type.
Restrict type parameter T in your ListOfFoo<T> class to implement this interface and to provide a parameterless constructor.
When you need the static method, construct a new dummy object of type T using the parameterless constructor and then call the instance method on that dummy instance.
Interface:
public interface IHaveFromBytesMethod<T>
{
T FromBytes(byte[] bytes, ref int index);
}
One of the Foo# classes:
public class Foo1 : IHaveFromBytesMethod<Foo1>
{
public Foo1()
{
// ...
}
public static Foo1 FromBytes(byte[] bytes, ref int index)
{
// ...
}
public Foo1 FromBytes(byte[] bytes, ref int index)
{
// within the instance method simply call the static method
return Foo1.FromBytes(bytes, ref index);
}
}
The modified ListOfFoo<T> class:
// requires T to implement the interface and provide a parameterless ctor!
public class ListOfFoo<T> : System.Collections.Generic.List<T>
where T : IHaveFromBytesMethod<T>, new()
{
public static ListOfFoo<T> FromBytes(byte[] bytes, ref int index)
{
// create dummy instance for accessing static method via instance method
T dummy = new T();
var count = bytes[index++];
var listOfFoo = new ListOfFoo<T>();
for (var i = 0; i < count; i++)
{
// instead of calling the static method,
// call the instance method on the dummy instance
listOfFoo.Add(dummy.FromBytes(bytes, ref index));
}
return listOfFoo;
}
}
I'd like to thank you all guys, you gave me some insights to think about. I've considered each approach and thought about its pros and con and wrote the following code. What do you think about? I think it is a good compromise for usability, readability and performance. It only lacks the compiler check.
public class ListOfFoo<T> : System.Collections.Generic.List<T>
{
private static readonly FromBytesFunc<T> BytesFromFunc =
(FromBytesFunc<T>)System.Delegate.CreateDelegate(
typeof(FromBytesFunc<T>),
typeof(T).GetMethod("FromBytes"));
private delegate T2 FromBytesFunc<out T2>(byte[] bytes, ref int index);
public static ListOfFoo<T> FromBytes(byte[] bytes, ref int index)
{
var count = bytes[index++];
var listOfFoo = new ListOfFoo<T>();
for (var i = 0; i < count; i++)
{
listOfFoo.Add(BytesFromFunc(bytes, ref index));
}
return listOfFoo;
}
}
This shall be the summary for all future viewers.
Since you cannot just call the method, the main problem is to get the delegate. There are two approaches:
via reflection
from the caller
You might think reflection is slow, but performance is not an issue. If the delegate is stored in a static field, it only needs to be done once per class, because generic types don't share static members.
Compile time verifiability is an issue. If you care much about compile time verifiability you should go with passing the delegate from the caller. If you care more about a clean method call you have to sacrifice the compile time verifiability.
PS: Some people have suggested to have a dictionary or a switch/case or if/else where the delegates are stored. This is something you shouldn't do. This has no advantage over storing the delegate in a static field of the generic class (generic types don't share static members).

How to make a copy of an object (not its reference) that is actually struct?

I have a value (struct instance) that was cast to object for generic handling. I need to make a copy of the value. I cannot do this explicitly because I just have its Type and don't know what it is in compile time.
By default I get a copy of reference: var copy = objectOfMyStruct;. I thought about making an explicit shallow copy by MemberwiseClone() but I cannot do this because it's protected method and I cannot modify MyStruct.
Convert.ChangeType(objectOfMyStruct, typeOfMyStruct) doesn't help because conversion (actually no conversion) happens inside and it returns Object again.
How could I do this?
EDIT:
I need to make a copy to preserve original value and just deserialized one to pass to OnChangeHandler. Simplified implementation is:
var oldValue = type.GetValue(reference);
var newValue = oldValue; // something better is needed here
Deserialize(type, stream, ref newValue);
OnChange(oldValue, newValue);
type.SetValue(reference, newValue);
Copy is made because only delta (changes) are sent so should be applied to the original value.
EDIT 2:
This implementation works fine for primitive types, so despite int is boxed too I'm copying it instead of copying reference to it. I just don't understand this.
Here is an example of what is needed.
This example, which you can test in LINQPad should make a clone of the struct without casting it back to its unboxed type, so that when it is mutated by a call through the implemented interface, only the original is mutated. The question is thus; how do I write that Clone method?
void Main()
{
object original = new Dummy { Property = 42, Field = "Meaning of life" };
object clone = Clone(original);
((IDummy)original).Mutate(); // will modify the boxed struct in-place
original.Dump();
// should output different if Clone did its job
clone.Dump();
}
static object Clone(object input)
{
return input;
}
public interface IDummy
{
void Mutate();
}
public struct Dummy : IDummy
{
public int Property { get; set; }
public string Field;
public void Mutate()
{
Property = 77;
Field = "Mutated";
}
}
I assume that you not only want to make a copy, but also be able to actually use that copy.
And in order to use it, you need to cast (unbox) it to the appropriate type, which effectively makes a copy. In fact, even putting the value into the box already resulted in a copy.
So, if (for example) you know that these objects are either ints or floats, you could do:
if (obj is int)
{
int i = (int) obj;
// do something with the copy in i
}
else if (obj is float)
{
float f = (float) obj;
// do something with the copy in f
}
If you have a large number of types to evaluate, you can use a switch statement or even a Dictionary<Type,Action<object>>.
If you need to deal with types that you don't know about at compile time (some type added dynamically thorugh some kind of plugin mechanism) than this won't be possible, but then again, it would also not be possible to do anything with the object (unless through an interface).
UPDATE:
Now that you changed your question, here's a better answer: you do no need to make a copy, it has been made for you by boxing the struct.
Example:
int i = 42;
// make a copy on the heap
object obj = i;
// modify the original
i = i + 1;
// copy is not modified
Debug.Assert((int)obj == 42);
Obviously, I'm using int here for convenience, but it is true for every struct. If the struct implements an interface, you can cast the object to that interface (that won't make a second copy) and use it. It will not modify the orginal value, because it is operating on the copy in the box.
UPDATE 2:
Just to be very explicit: this works for every struct. For example:
interface IIncrementor
{
void Increment();
}
struct MyStruct : IIncrementor
{
public int i;
public void Increment()
{
this.i = this.i + 1;
}
public override string ToString()
{
return i.ToString();
}
}
// in some method:
MyStruct ms = new MyStruct();
ms.i = 42;
Console.Writeline(ms); // 42
object obj = ms;
IIncrementable ii = (IIncrementable) obj;
ii.Increment();
Console.Writeline(ms); // still 42
Console.Writeline(ii); // 43
One more UPDATE:
instead of
object original = new Dummy { Property = 42, Field = "Meaning of life" };
object clone = Clone(original);
write
Dummy original = new Dummy { Property = 42, Field = "Meaning of life" };
object clone = original;
and you'll be fine.
Thanks for the LINQPad example, it greatly clarified your question and it gave me a starting point for coming up with a solution.
This is a very brute-force solution, but it might serve your purpose, until somebody comes up with a more elegant answer:
static object Clone(object input)
{
IntPtr p = Marshal.AllocHGlobal(Marshal.SizeOf(input));
try
{
Marshal.StructureToPtr(input, p, false);
return Marshal.PtrToStructure(p, input.GetType());
}
finally
{
Marshal.FreeHGlobal(p);
}
}
This is how it works:
It allocates unmanaged memory large enough to hold your struct.
StructureToPtr unboxes your input and copies it into unmanaged memory:
If structure is a value type, it can be boxed or unboxed. If it is boxed, it is unboxed before copying.
PtrToStructure creates a new structure, boxes it and returns it:
You can pass a value type to this overload method. In this case, the returned object is a boxed instance.
The unmanaged memory is freed.
Here's another answer:
static object Clone(object input) =>
typeof(object)
.GetMethod("MemberwiseClone", BindingFlags.NonPublic | BindingFlags.Instance)
.Invoke(input, null);
It uses the Object.MemberwiseClone method. This method is protected, which is why I have to call it via reflection.
This approach works fine with enums, and with structs that have [StructLayout(LayoutKind.Auto)].
If the list of types to handle this cloning for is controlled, that is, you know which types you need to handle this for, then I would simply create a dictionary that contains functions that knows how to handle each particular type.
Here's a LINQPad example:
void Main()
{
_CloneMapping[typeof(Dummy)] = (object obj) =>
{
Dummy d = (Dummy)obj;
return new Dummy { Field = d.Field, Property = d.Property };
};
object original = new Dummy { Property = 42, Field = "Meaning of life" };
object clone = Clone(original);
((IDummy)original).Mutate(); // will modify the boxed struct in-place
original.Dump();
// should output different if Clone did its job
clone.Dump();
}
static readonly Dictionary<Type, Func<object, object>> _CloneMapping = new Dictionary<Type, Func<object, object>>();
static object Clone(object input)
{
if (input == null)
return null;
var cloneable = input as ICloneable;
if (cloneable != null)
return cloneable.Clone();
Func<object, object> cloner;
if (_CloneMapping.TryGetValue(input.GetType(), out cloner))
return cloner(input);
throw new NotSupportedException();
}
public interface IDummy
{
void Mutate();
}
public struct Dummy : IDummy
{
public int Property { get; set; }
public string Field;
public void Mutate()
{
Property = 77;
Field = "Mutated";
}
}
This will output:

Passing a class property as a parameter

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.

Struct wrapping value types and giving access with an index

I need to encapsulate an fixed array of a user defined value type (let's call it struct2 ) inside an other struct (struct1) but fixed arrays can be declared only for native value types. So i thought to create a third struct (struct wrapper) that has to work as an array of the struct2 by defining the [] operator.
So
struct Struct2
{
int a;
int b
}
struct wrapper
{
Struct2 str0;
Struct2 str1;
public Struct2 this[int index]
{
get
{
switch ( index )
{
case 0: return str0;
case 1: return str1;
default: return str0;
}
}
}
}
static void Main()
{
wrapper wr = new wrapper();
wr[0].a = 123; // i would like to do this but this doesnt work
//but if we do like this
Struct2 [] arr = new Struct2[5];
arr[0].a = 123 ;// this works , we are effectively modifying the object
//contained in the array (not just a copy)
}
Ok, this code doesn't work because Struct2 is a value type and when the operator returns then it returns a copy and not the actual object str0 contained in it. I would like to access that field using an indexer ! is it possible ? Why it's possible with the Array class ?
I know that it's possible by returning a pointer but this involve using the fixed keyword inside the operator definition and i would like to avoid that because the 'array' need to be accessed extensively and i would end up by using the fixed statement 2 times (inside and outsid to keep the address fixed). Also i already considered using pointers by just declaring N adiacent Struct2 fields in Struct1 and using a pointer to the first one as an array but i would prefer to use the wrapper to emulate an array behaviour.
Agai , is it possible?
Edit
It seems that it's not possible to implement a custom array that works with value types(as common arrays do).
Btw the nearest solution i could find is this, but as i wrote i would have liked to avoid pointers.
struct Struct2
{
int a;
int b
}
struct Struct1
{
public Struct2 * str2arr ; //this can be avoided
public Struct2 str0;
//wrapper is not needed anymore as Struct1 is wrapping the Struct2 array by itself
//and a pointer is used for indexing operations
//struct layout needs to be sequential
private Struct2 str1;
private Struct2 str2;
private Struct2 str3;
private Struct2 str4;
}
static void Main()
{
Struct1 myStruct = new Struct1();
fixed(myStruct.str2arr = &myStruct.str0)
{
myStruct.str2arr[1] = 123;
}
}
You cant do what you want because Struct2 is a value type. The compiler will give you an error cannot modify return value because it is not a variable. because allowing you to do wr[0]==123 would be, to say the least, confusing as you would be modifying a copy of the value stored in the array which would be discarded.
I think you should reconsider quite a few things in your approach. First of all, do not use mutable value types, they only cause problems. Immutability is the way to go when it comes to value types. Second of all, if you need mutability and reference semantics then why use a struct at all? Consider using a class instead.
Otherwise, the closest you can get to the functionality you are looking for is exposing in your wrapper class the underlying Struct2 array as a readonly field.
public struct Wrapper(...)
{
public readonly Struct2[] Arr;
}
No you can do:
wr.Arr[0] = 123;
But of course you can also do:
wr.Arr[0] = new Struct2(...)
which could be a problem. You can circumvent this by makingStrutc2 constructors internal if possible.
Struct is known as value semantics that's why you cant modify value directly.
With classes, it is possible for two variables to reference the same object, and thus possible for operations on one variable to affect the object referenced by the other variable. With structs, the variables each have their own copy of the data (except in the case of ref and out parameter variables), and it is not possible for operations on one to affect the other.
You should think about using classes instead structs.
EDIT
If you really need to have Struct2 as struct then you can create wrapper as class. In class you can have fixed array of structures and modify it through method.
class wrapper
{
Struct2[] structArray = new Struct2[10];
public void setValues(int index, int a, int b)
{
structArray[index].a = a;
structArray[index].b = b;
}
}
wrapper wr = new wrapper();
wr.setValues(0, 2, 3);
You cannot achieve what you want to do without having at least a root class containing your data. Here is a solution which works for a stripped-down version of your problem, namely being able to access field a of your Struct2 in your pseudo-array, such as:
wrapper wr = new wrapper (); // needs to be a class
wr[0].a = 123;
wr[1].a = 456;
System.Console.WriteLine ("wr[0].a = {0}", wr[0].a); // displays 123
System.Console.WriteLine ("wr[1].a = {0}", wr[1].a); // displays 456
Your wrapper must return a reference type if you want to be able to modify its contents, or else you will always hit your head against the value-type copying taking place when you access structs. But your wrapper may still be storing its data internally as a series of structs.
Here is my solution:
struct Struct2
{
public int a;
}
class wrapper // sorry, cannot use 'struct' here ...
{
Struct2 str0;
Struct2 str1;
public helper this[int index]
{
get
{
return new helper (this, index);
}
}
int GetValueA(int index)
{
switch (index)
{
case 0: return str0.a;
case 1: return str1.a;
default: throw new System.IndexOutOfRangeException ();
}
}
void SetValueA(int index, int value)
{
switch (index)
{
case 0: str0.a = value; break;
case 1: str1.a = value; break;
}
}
public class helper
{
public helper(wrapper host, int index)
{
this.host = host;
this.index = index;
}
public int a
{
get { return this.host.GetValueA (index); }
set { this.host.SetValueA (index, value); }
}
private readonly wrapper host;
private readonly int index;
}
}
As your concern seems to be speed, then no wrapper will make you happy. I would reconsider the whole problem and, if at all possible, write a class to manage your data structure.
If all your data can be represented as int, maybe you should consider using a huge array of integers and then add classes which access that one central array to locate the fields you want to manipulate, by indexing into the proper item.
class Wrapper
{
...
int[] data;
public StructWrapper1 this[int index]
{
get
{
return new StructWrapper1 (this, index);
}
}
public class StructWrapper1
{
public StructWrapper1(Wrapper wrapper, int index)
{
this.wrapper = wrapper;
this.index = index;
}
public int A
{
get { return this.wrapper[this.index*2+0]; }
set { this.wrapper[this.index*2+0] = value; }
}
public int B
{
get { return this.wrapper[this.index*2+1]; }
set { this.wrapper[this.index*2+1] = value; }
}
private readonly Wrapper wrapper;
private readonly int index;
}
}
If you need to represent various data types, you could consider using one array for every field type.
I think you need to give up on the indexer here. Even though it looks the same when using it on an instance of a user defined type and an array it's not. When you define an indexer getter it's just syntactical sugar for a Get(int index) method and when you return a value type from a method it is returned by value, that's the whole point of a value type.
For example:
struct wrapper {
public Struct2 str0;
public Struct2 str1 { get; set; }
public Struct2 this[int index] {
get {
switch ( index ) {
case 1: return str1;
default: return str0;
}
}
}
}
static void Main(string[] args) {
wrapper wr = new wrapper();
wr.str0.a = 123; // Works, accessing fields only.
wr.str1.a = 123; // Does not work, str1 is a property, which is really a method
wr[0].a = 123; // Also does not work
}
I can't come up with any way of doing what you want with an indexer without creating any intermediate reference type instances. So this probably leaves creating methods for setting the the values of the inner struct based on index (as suggested by Renius).

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