Alternative to using ref in foreach? - c#

I have a modifying method with a signature like
private bool Modify(ref MyClass obj);
that will make modifications to obj and indicate succes with it's return value. Modify is not reassigning the reference (I know that this wouldn't work), just modifying instance fields, so I want to use it to do something like the following:
foreach(MyClass obj in myList)
{
bool success = Modify(obj);
// do things depending on success
}
I am running into a problem compiling as obj is "not being passed with the ref keyword". However, if I put the ref keyword in like so:
bool success = Modify(ref obj);
I get "cannot use obj as a ref/out because it is a 'foreach iteration variable". I understand that foreach uses an immutable iterator and that's why this doesn't work.
My question is what is the easiest alternative to make something like this work?
I have tried using
foreach(int i = 0; i < myList.Count; i++)
{
bool success = Modify(ref myList[i]);
// do things depending on success
}
but they I get "a property or indexer may not be passed as an out of ref parameter".
Thanks your help.

Any type within C# is passed actually by value. When you pass an instance of a class to a method what is actually passed is not the instance itself but a reference to it which itself is passed by value. So effectivly you're passing instances of a class as reference - which is why you call them reference-types.
In your case you just modify an existing instance referenced by that reference-value in your method, no need to use the ref-keyword.
foreach(var m in myList)
{
MyMethod(m);
}
MyMethod(MyClass instance)
{
instance.MyProperty = ...
}
If you'd really pass the reference by reference you'd re-assign the obj on every iteration within your loop which isn't allowed within a foreach-block. This would be similar to the following:
foreach(var m in myList)
{
m = new MyClass();
}
On the other side you could also use a classic for-loop. However you'd need a temporary variable to store the outcome of your method:
for(int i = 0; i < myList.Length; i++)
{
var tmp = myList[i];
MyMethod(ref tmp);
myList[i] = tmp;
}

You state
Modify is not reassigning the reference
Therefore, there is no reason the Modify(ref MyClass) function needs to pass argument by ref.
You should be able to do the same "modifications", whatever that is (please clarify that) by passing the object reference by value, i.e. removing the ref keyword.
So, the fix here should be changing your Modify function signature from Modify(ref MyClass) to Modify(MyClass)

use a temp variable to bypass the message
foreach(MyClass obj in myList)
{
MyClass objTemp = obj;
bool success = Modify(ref objTemp);
// do things depending on success
}
private MyMethod(ref MyClass instance)
{
instance.MyProperty = ...
}

It is solved by using LINQ.
My Code:
private static List<string> _test = new List<string>();
public List<string> Test { get => _test; set => _test = value; }
static void Main(string[] args)
{
string numString = "abcd";
_test.Add("ABcd");
_test.Add("bsgd");
string result = _test.Where(a => a.ToUpper().Equals(numString.ToUpper()) == true).FirstOrDefault();
Console.WriteLine(result + " linq");
}

You need to cast your array to a Span:
int[] nums = new[] { 1, 2, 3, 4, 5 };
int i = 0;
foreach (ref var item in nums.AsSpan())
{
item += 10;
Console.WriteLine(nums[i++]);
}
output:
11
12
13
14
15
You can modify the iteration variable because Span Enumerator's Current property is of ref T type.

Related

Trying to map "similar looking" tuples returned from multiple functions to one variable

Say there is a library with code of this form:
public class SomeLib
{
public (bool WasOk, string Message) DoCheck(string fileName)
{
// do something here to check the file.
return (true, "all good");
}
public (bool WasOk, string Message) DoCheck(byte[] fileBytes)
{
// do something here to check the file as bytes
return (true, "all good");
}
}
The code which uses this library looks of this form:
int option = 1;
SomeLib lib = new SomeLib();
if (option == 0)
{
var res1 = lib.DoCheck("hello");
MessageBox.Show(res1.WasOk + res1.Message);
}
else
{
var res2 = lib.DoCheck(new byte[] { });
MessageBox.Show(res2.WasOk + res2.Message);
}
What I was hoping to do, was to store the returned value from the two calls to DoCheck, to a common variable. e.g.:
int option = 1;
SomeLib lib = new SomeLib();
var res; // doesn't compile, obviously
if (option == 0)
{
res = lib.DoCheck("hello");
}
else
{
res = lib.DoCheck(new byte[] { });
}
MessageBox.Show(res.WasOk + res.Message); // act on the result in the same way for both branches.
I hope this makes sense. Is what I am trying to do possible? Let's say that the code in the library cannot be changed.
var res doesn't compile because it doesn't have any type information. If you're making a statement that declares a variable the compiler has to be able to work out the type somehow, either from the left or the right side:
StringBuilder sb = new StringBuilder(); //both sides, available from the dawn of time
var sb = new StringBuilder(); //for a long time
StringBuilder sb = new(); //more recently
If there isn't a right side then the left side has to have the type info:
StringBuilder sb;
Thus for your case you need to put the type info on the left. You can even rename the members (but you don't have to)
(bool AllGood, string Note) res;
(bool WasOk, string Message) res;
(bool, string) res; //access the bool in res.Item1, string in res.Item2
You could do it in a one with a ternary:
var res = (option == 0) ? lib.DoCheck(hello) : lib.DoCheck(new byte[] { });
Both your methods return tuples with the same named members so your res will have res.WasOk and res.Message so it's compiled as if it's this:
(bool WasOk, string Message) res = ...
If your tuples coming out your methods had different names it would still compile as if it was this:
(bool, string) res = ...
And you could still access the data via Item1 and Item2
If you're doing this ternary approach then you could deconstruct the tuple too, which also allows you to rename:
var(allGood, note) = ... ? ... : ... ;
MessageBox.Show(note);
Instead of one tuple variable where you say res.Whatever, this has created two variables like as if you'd done this:
var res = ... ? ... : ... ;
var allGood = res.WasOk;
var note = res.Message;
Plenty of options for dealing with tuples..
Implicitly typed locals must be initialized
An implicitly typed local variable must be initialized with a value at the same time that it is declared. here
To correct this error
Assign a value to the variable or else give it an explicit type.
(bool AllGood, string Note) res;

How to overwrite a point in memory in c#?

I want to do have the following functionality:
var item0 = new Item();
var item1 = item0;
item0 = null;
Console.WriteLine(item1 == null); // true
So I'd be overwriting the memory that item0 and item1 point to.
I figured maybe I could do this with pointers..? However, when I tried declaring an item pointer:
Item* itemPointer;
i got an error. Any ideas?
Since C# 7 You can use Ref Locals:
var item0 = new Item();
ref var item1 = ref item0;
item0 = null;
Console.WriteLine(item1 == null); // true
// THIS WORKS!
Ref returns and ref locals have mainly been introduced to avoid copying large structs in time sensitive scenarios like gaming where large arrays of vectors have to be processed. I don't see the advantage in using them with reference types. They tend to make the code hard to understand, thus I would restrict their use to exceptional and rare cases.
var item0
{
get{return item0;}
set
{
item0 = value;
item1 = item0;
}
}
Something like this will overwrite the value of item1 every time the value of item0 changes.
There are no local aliases/references in C#
However there is a ref keyword for arguments:
static void RefClean(ref String arg){
arg = null;
}
static void Main(string[] args)
{
var test = "Hello";
Console.WriteLine(test == null);
RefClean(ref test);
Console.WriteLine(test == null);
}
For pointers you need the unsafe keyword, and you have to use unmanaged types only (primitive types and structures built from them), which rules out your case with objects/references. See https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/unsafe-code-pointers/pointer-types for some overview.

Detect if an object is a ValueTuple

I have a use case where I need to check if a value is a C# 7 ValueTuple, and if so, loop through each of the items. I tried checking with obj is ValueTuple and obj is (object, object) but both of those return false. I found that I could use obj.GetType().Name and check if it starts with "ValueTuple" but that seems lame to me. Any alternatives would be welcomed.
I also have the issue of getting each item. I attempted to get Item1 with the solution found here: How do I check if a property exists on a dynamic anonymous type in c#? but ((dynamic)obj).GetType().GetProperty("Item1") returns null. My hope was that I could then do a while to get each item. But this does not work. How can I get each item?
Update - more code
if (item is ValueTuple) //this does not work, but I can do a GetType and check the name
{
object tupleValue;
int nth = 1;
while ((tupleValue = ((dynamic)item).GetType().GetProperty($"Item{nth}")) != null && //this does not work
nth <= 8)
{
nth++;
//Do stuff
}
}
Structures do not inherit in C#, so ValueTuple<T1>, ValueTuple<T1,T2>, ValueTuple<T1,T2,T3> and so on are distinct types that do not inherit from ValueTuple as their base. Hence, obj is ValueTuple check fails.
If you are looking for ValueTuple with arbitrary type arguments, you can check if the class is ValueTuple<,...,> as follows:
private static readonly Set<Type> ValTupleTypes = new HashSet<Type>(
new Type[] { typeof(ValueTuple<>), typeof(ValueTuple<,>),
typeof(ValueTuple<,,>), typeof(ValueTuple<,,,>),
typeof(ValueTuple<,,,,>), typeof(ValueTuple<,,,,,>),
typeof(ValueTuple<,,,,,,>), typeof(ValueTuple<,,,,,,,>)
}
);
static bool IsValueTuple2(object obj) {
var type = obj.GetType();
return type.IsGenericType
&& ValTupleTypes.Contains(type.GetGenericTypeDefinition());
}
To get sub-items based on the type you could use an approach that is not particularly fast, but should do the trick:
static readonly IDictionary<Type,Func<object,object[]>> GetItems = new Dictionary<Type,Func<object,object[]>> {
[typeof(ValueTuple<>)] = o => new object[] {((dynamic)o).Item1}
, [typeof(ValueTuple<,>)] = o => new object[] {((dynamic)o).Item1, ((dynamic)o).Item2}
, [typeof(ValueTuple<,,>)] = o => new object[] {((dynamic)o).Item1, ((dynamic)o).Item2, ((dynamic)o).Item3}
, ...
};
This would let you do this:
object[] items = null;
var type = obj.GetType();
if (type.IsGeneric && GetItems.TryGetValue(type.GetGenericTypeDefinition(), out var itemGetter)) {
items = itemGetter(obj);
}
Regarding the part of the question "How can I get each item?"...
Both ValueTuple and Tuple both implement ITuple, which has a length property and an indexer property. So a the following console app code lists the values to the console:
// SUT (as a local function)
IEnumerable<object> GetValuesFromTuple(System.Runtime.CompilerServices.ITuple tuple)
{
for (var i = 0; i < tuple.Length; i++)
yield return tuple[i];
}
// arrange
var valueTuple = (StringProp: "abc", IntProp: 123, BoolProp: false, GuidProp: Guid.Empty);
// act
var values = GetValuesFromTuple(valueTuple);
// assert (to console)
Console.WriteLine($"Values = '{values.Count()}'");
foreach (var value in values)
{
Console.WriteLine($"Value = '{value}'");
}
Console output:
Values = '4'
Value = 'abc'
Value = '123'
Value = 'False'
Value = '00000000-0000-0000-0000-000000000000'
This is my solution to the problem. A PCL compatible extension class. Special thanks to #dasblinkenlight and #Evk for helping me out!
public static class TupleExtensions
{
private static readonly HashSet<Type> ValueTupleTypes = new HashSet<Type>(new Type[]
{
typeof(ValueTuple<>),
typeof(ValueTuple<,>),
typeof(ValueTuple<,,>),
typeof(ValueTuple<,,,>),
typeof(ValueTuple<,,,,>),
typeof(ValueTuple<,,,,,>),
typeof(ValueTuple<,,,,,,>),
typeof(ValueTuple<,,,,,,,>)
});
public static bool IsValueTuple(this object obj) => IsValueTupleType(obj.GetType());
public static bool IsValueTupleType(this Type type)
{
return type.GetTypeInfo().IsGenericType && ValueTupleTypes.Contains(type.GetGenericTypeDefinition());
}
public static List<object> GetValueTupleItemObjects(this object tuple) => GetValueTupleItemFields(tuple.GetType()).Select(f => f.GetValue(tuple)).ToList();
public static List<Type> GetValueTupleItemTypes(this Type tupleType) => GetValueTupleItemFields(tupleType).Select(f => f.FieldType).ToList();
public static List<FieldInfo> GetValueTupleItemFields(this Type tupleType)
{
var items = new List<FieldInfo>();
FieldInfo field;
int nth = 1;
while ((field = tupleType.GetRuntimeField($"Item{nth}")) != null)
{
nth++;
items.Add(field);
}
return items;
}
}
hackish one liner
type.Name.StartsWith("ValueTuple`")
(can be extended to check the digit at the end)

Atomically reading values of fields via reflection

Let's suppose I have the following C# declaration:
struct Counters
{
public long a;
public long b;
public long c;
}
Is this possible to iterate through the fields of a given instance of Counters and read their values using Interlocked.Read()? I.e.
Counters counters;
foreach (var counter in typeof(Counters).GetFields())
{
var value = Interlocked.Read(???);
}
You can't use Interlocked.Read directly, because it requires a ref argument - and you can't use the required System.Int64& type directly.
So, back to reflection:
// You can keep this static in some helper class
var method = typeof(Interlocked).GetMethod("Read", new []{ typeof(long).MakeByRefType() });
var result = (long)method.Invoke(null, new object[] { counter.GetValue(instance) });
EDIT: This doesn't work either, I botched up my testing. You're still reading a copy that wasn't produced atomically.
This will work, though:
public delegate long AtomicReadDelegate<T>(ref T instance);
public static AtomicReadDelegate<T> AtomicRead<T>(string name)
{
var dm = new DynamicMethod(typeof(T).Name + "``" + name + "``AtomicRead", typeof(long),
new [] { typeof(T).MakeByRefType() }, true);
var il = dm.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldflda, typeof(T).GetField(name));
il.Emit(OpCodes.Call,
typeof(Interlocked).GetMethod("Read", new [] { typeof(long).MakeByRefType() }));
il.Emit(OpCodes.Ret);
return (AtomicReadDelegate<T>)dm.CreateDelegate(typeof(AtomicReadDelegate<T>));
}
private readonly AtomicReadDelegate<Counters>[] _allTheReads =
new []
{
AtomicRead<Counters>("a"),
AtomicRead<Counters>("b"),
AtomicRead<Counters>("c")
};
public static void SomeTest(ref Counters counters)
{
foreach (var fieldRead in _allTheReads)
{
var value = fieldRead(ref counters);
Console.WriteLine(value);
}
}
You might want to cache the delegates you get from AtomicRead - they can be reused safely. A simple concurrent dictionary will work just fine.
Don't forget that this only supports longs; you'll need to use Interlocked.CompareExchange if you need to atomically read other types as well (apart from references and ints, of course - though depending on your code, you might need some memory barriers even in that case).
Values for instance fields are per object, so you need to take the value for a particular object.
Counters counter1 = new Counter() { a = 40; b = 50; c = 60; }
Type counterType = counter1.GetType();
foreach (var field in counterType.GetFields())
{
var value = Interlocked.Read(field.GetValue(counter1));
}
In this case we get values for the fields of counter1 and not any other struct instance.
If you really need an atomic long, then it's better to use atomics.net library (which is available via NuGet).
If you need just read values of struct passed in your thread, then it's safe to read, since it's passed by value. But if it's passed by reference or if you work with unsafe/native code, then it's better to say what exactly you want to achieve.

Return value, Ref, Out is there any difference? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I am doing this,
public Order Add(Order order)
{
order.thisA = GetValue1();
// update the state of object
return order;
}
Would i be any beneficial if I use Ref or Out here instead ?
Further implementation would require me to add this method,
public Order[] UpdateCollection(Order[] orderCollection)
{
foreach(Order o in orderCollection)
o = Update(o);
return orderCollection;
}
Please tell me in light of best practices as well.
Context:
At the moment I am only returning INT id of the order but in future maybe I need to return more properties, but here is the full context,
https://codereview.stackexchange.com/questions/97778/crud-operation-class#
In this case:
public MyObject Update(MyObject object)
{
object.thisA = GetValue1();
// update state of object
return object;
}
You are not changing MyObjects reference so:
You don't need to return the object back.
You don't need to use ref.
You don't need to use out.
Using out is for initializing an object (You must assign a value in the function).
MyObject obj; // didn't assign anything
Method(out obj);
public void Method(out MyObject obj){
obj = new MyObject(); // assigned
}
using ref is in case you might change the reference of the object inside the method:
MyObject obj = new MyObject();
Update(ref obj);
public void Update(ref MyObject obj)
{
obj = new MyObject(); // changing the ref!!!
obj.thisA = GetValue1();
}
BTW, in your case you don't need to do anything:
public void UpdateCollection(Order[] orderCollection)
{
foreach(Order o in orderCollection)
Update(o);
}
public void Update(MyObject object)
{
object.thisA = GetValue1();
}
You are foreaching an array and updating the object and not the reference.
You use ref if there is a chance that you want to change the reference instead of the object's data.
Example:
public void RetargetReference(ref List<string> originalList)
{
originalList = new List<string>();
originalList.Add("World");
}
List<string> inList = new List<string>();
inList.Add("Hello");
RetargetReference(ref inList);
This will change the reference of inList. It will now point to a new list which contains one entry "World". The list that contained "Hello" will no longer be available to you unless you have another reference to it.
ref parameters can be useful if you want to change parameter you passed in during the execution of the method.
out will be used to have the method create a new object instance without you being able to pass a value in!
Example:
public void CreateReference(out List<string> newList)
{
newList = new List<string>();
newList.Add("Hello World");
}
List<string> list;
CreateReference(out list);
After that, list will point to a new List<string> instance. Inside the method you have no access to whatever newList actually "points to". You will always have to create a new instance.
out parameters can be useful if you want your method to return more than one result. For example, the following method would return a bool to indicate success and two out parameters that contain the data:
public bool TrySplitString(string source, out string part1, out string part2)
{
part1 = String.Empty;
part2 = String.Empty;
string[] parts = source.Split('=');
if (parts.Length != 2)
return false;
part1 = parts[0];
part2 = parts[1];
return true;
}
Objects are generally passed by reference in C#, so the following method actually changes the data "outside" the method:
public void ChangeList(List<string> list)
{
list.Add("World");
}
List<string> inList = new List<string>();
inList.Add("Hello");
ChangeList(inList);
After that, inList contains two entries: "Hello" and "World".
The reason why sometimes you return the object that was passed in as a parameter is that this allows so called "method chaining" where you can "write sentences" instead of "commands". You'll see that in my next example:
public static List<string> CreateList()
{
return new List<string>();
}
public static List<string> AddItem(this List<string> list, string item)
{
list.Add(item);
return list;
}
public static List<string> DoSomethingWithList(this List<string> list)
{
...;
return list;
}
You can use this code and write something like this:
List<string> list = CreateList().AddItem("Hello").DoSomethingWithList();
Return object back may be used for create "method chaining", like this:
someObject.Update(MyObject object).MyObjectMethod1().MyObjectMethod2();
I can't really workout what you really trying to achieve. However, i will give you some basics.
In C#, arguments can be passed to parameters either by value or by reference.
If your MyObject is a reference type (eg: class) then it is passed to function as reference and hence you will end up in modifying same object. In other way, any change you make on this instance (within the function) will have a direct impact on that instance and it will continue to be true in the current execution environment.
On the other hand, if MyObject is a value type (eg: struct) then a copy of it will be passed to method. That is, original instance of your value type is not altered even if you modify the members within the method. This is default behavior when it comes to value type.
Now assume a scenario where you wanted to modify the original instance of value type. This can be achieved only if you pass the reference of your value type. Here comes ref and out. Using these keyword, you can pass parameter by reference. There are differences between ref and out, which can be learned separately. However, keeping your context in mind, the ref and out both allow the called method to modify a parameter.
ref means that the parameter has a value on it before going into the function. So that the function can read and or change the value within it. On the other hand, out means that the parameter has no official value before going into the function. The called function must initialize it before parameter goes out from function.

Categories