C#: Good/best implementation of Swap method - c#

I read this post about card shuffling and in many shuffling and sorting algorithms you need to swap two items in a list or array. But what does a good and efficient Swap method look like?
Let's say for a T[] and for a List<T>. How would you best implement a method that swaps two items in those two?
Swap(ref cards[i], ref cards[n]); // How is Swap implemented?

Well, the code you have posted (ref cards[n]) can only work with an array (not a list) - but you would use simply (where foo and bar are the two values):
static void Swap(ref int foo, ref int bar) {
int tmp = foo;
foo = bar;
bar = tmp;
}
Or possibly (if you want atomic):
Interlocked.Exchange(ref foo, ref bar);
Personally, I don't think I'd bother with a swap method, though - just do it directly; this means that you can use (either for a list or for an array):
int tmp = cards[n];
cards[n] = cards[i];
cards[i] = tmp;
If you really wanted to write a swap method that worked on either a list or an array, you'd have to do something like:
static void Swap(IList<int> list, int indexA, int indexB)
{
int tmp = list[indexA];
list[indexA] = list[indexB];
list[indexB] = tmp;
}
(it would be trivial to make this generic) - however, the original "inline" version (i.e. not a method) working on an array will be faster.

11 years later and we have tuples...
(foo, bar) = (bar, foo);

A good swap is one where you don't swap the contents. In C/C++ this would be akin to swapping pointers instead of swapping the contents. This style of swapping is fast and comes with some exception guarantee. Unfortunately, my C# is too rusty to allow me to put it in code. For simple data types, this style doesn't give you much. But once you are used to, and have to deal with larger (and more complicated) objects, it can save your life.

What about this?
It's a generic implementation of a swap method. The Jit will create a compiled version ONLY for you closed types so you don't have to worry about perfomances!
/// <summary>
/// Swap two elements
/// Generic implementation by LMF
/// </summary>
public static void Swap<T>(ref T itemLeft, ref T itemRight) {
T dummyItem = itemRight;
itemLeft = itemRight;
itemRight = dummyItem;
}
HTH
Lorenzo

Use:
void swap(int &a, int &b)
{
// &a != &b
// a == b OK
a ^= b;
b ^= a;
a ^= b;
return;
}
I did not realize I was in the C# section. This is C++ code, but it should have the same basic idea. I believe ^ is XOR in C# as well. It looks like instead of & you may need "ref"(?). I am not sure.

You can now use tuples to accomplish this swap without having to manually declare a temporary variable:
static void Swap<T>(ref T foo, ref T bar)
{
(foo, bar) = (bar, foo)
}

For anyone wondering, swapping can also be done also with Extension methods (.NET 3.0 and newer).
In general there seems not to be possibility to say that extension methods "this" value is ref, so you need to return it and override the old value.
public static class GeneralExtensions {
public static T SwapWith<T>(this T current, ref T other) {
T tmpOther = other;
other = current;
return tmpOther;
}
}
This extension method can be then used like this:
int val1 = 10;
int val2 = 20;
val1 = val1.SwapWith(ref val2);

Related

How to move two enumerators simultaneously?

I have two big arrays of two readonly structs: A and B. I need to enumerate over them but I need to do it in the most optimized way.
readonly struct A {
long a;
long b;
long c;
long d;
long e;
long g;
}
readonly struct B {
byte a;
ushort b;
}
As you can see Type A is very large struct to copy it over and over again so I made my custom enumerator that returns this struct by reference (ref return). Type B doesn't need it because its' size is only 4 bytes. Now I need to make two enumerators move simultenously using only single foreach cycle because it doesn't look much native calling Enumerator's methods directly (i.e. MoveNext, Current) and so on.
My problem is that when I try to save two structs in one single aggregate struct A is copied and I lose my perfomance gain.
public readonly struct Aggregate
{
public readonly A ItemA;
public readonly B ItemB;
public Aggregate(A itemA, in B itemB)
{
ItemA = itemA;
ItemB = itemB;
}
}
The total size of this aggregate will have size of 56 bytes. It sounds logical that C# copies the struct when I assign it to the property of another struct. But what can I do with it? I need only the reference to the element of an array. Using unsafe code to get a pointer is not a right way, I think, because GC can move my array (if it's small enough and not located in LOH area).
So what solutions could you propose to me?
I don't know whether I understand your question correct or not, but your talking about arrays.
Assumption: Both are arrays of same size
You can do that
for (int i = 0; i < length; i++)
{
ref var aItem = ref arrayA[i];
ref var bItem = ref arrayB[i];
//do your stuff
}
You can use the enumerators explicitly, without a foreach-loop:
var aEnumerator = listA.GetEnumerator();
var bEnumerator = listB.GetEnumerator();
while (aEnumerator.MoveNext() && bEnumerator.MoveNext()) {
var aItem = aEnumerator.Current;
var bItem = bEnumerator.Current;
//TODO: do some work
}

TryParse create inline parameter?

Is there any way in C# to create a variable inline?
Something like this:
int x = int.TryParse("5", out new int intOutParameter) ? intOutParameter : 0;
Don´t you think that this is more useful than creating a variable outside and then never use it again?
That syntax – called declaration expressions – was on the proposed feature list for the next version of C# (version 6).
You're not the only one to think it is useful. For instance making a complete TryParse call an expression (no need for a statement to declare the variable).
However it has been dropped from the ongoing work to C#6.
I'm sure I'm not the only one hoping it will make a return in a future version.It is included in C#7 as a declaration (no need for new):
int x = int.TryParse("5", out int intOutParameter) ? intOutParameter : 0;
Inline declarations for out params is a new suggested feature in C# that might be standard one day, see e.g. Probable C# 6.0 features illustrated, section 9. The expected/proposed syntax:
int.TryParse("5", out int x); // this declares (and assigns) a new variable x
Edit: This out variable syntax was eventually included in C# 7.0 (Visual Studio 2017); you can also use out var x.
Addition: People come up with fun extension methods. I tried to make a generic one:
public delegate bool TryParser<TResult>(string s, out TResult result);
public static class FunExtensions
{
public static T TryParse<T>(this string str, TryParser<T> tryParser)
{
T outResult;
tryParser(str, out outResult);
return outResult;
}
}
This can be used like this:
var x = "5".TryParse<int>(int.TryParse);
var y = "01/01".TryParse<DateTime>(DateTime.TryParse);
var z = "bad".TryParse<decimal>(decimal.TryParse);
and so on. I was hoping the compiler would infer T from usage, so that one could say simply:
var x = "5".TryParse(int.TryParse); // won't compile
but it appears you have to explicitly specify the type argument to the method.
As a workaround you could create an extension:
public static int TryParse(this string input, int defaultValue = default(int))
{
int intOutParameter;
bool parsable = int.TryParse(input, out intOutParameter);
if (parsable)
return intOutParameter;
else
return defaultValue;
}
Then you don't even need an out-parameter:
int parsed = "5".TryParse(0);
Based on OP request:
private static bool IsIntValid(string str)
{
int i = 0;
return int.TryParse(str, out i);
}
Granted not the most cleverest approach however, the simplest I guess :) Can wrap this in an extension method also perhaps.
You can also use a temporary storage for all methods.
public static class Tmp<T>
{
[ThreadStatic]
public static T Value;
}
 
int x = int.TryParse("5", out Tmp<int>.Value) ? Tmp<int>.Value : 0;

Building generic method for List<Enum>

In my application, I have something like:
public enum Locations {
LocationA,
LocationB,
LocationC
}
private List<Locations> _myLocations;
public Int64 PackedLocations {
get {
return PackEnumList(this._myLocations);
}
}
So: an enum (backed by int), a List of those enum values, and a read-only property which returns the result of a method I've left out so far.
That method, PackEnumList, is meant to give me a 64-bit integer where each BIT denotes whether the corresponding enum value was selected or not in a list of unique enum values. So in my example above, if _myLocations has only one item: {Locations.LocationA}, the result would be 1 (binary: ...00001), if we then add Locations.LocationC to that list, the result would be 5 (binary: ...000101). The implementation isn't important right now (but I'll include it below for completion/interest/feedback), but the signature of that method is:
public Int64 PackEnumList(List<Enum> listOfEnumValues) {
...
}
When I compile, I get an error that "the best overloaded method ... has some invalid arguments".
I'm guessing this is because _myLocations is being seen as a List of int values, but I'd like PackEnumList() to work even if the enumeration being used were backed by something else, if possible.
Is there a more appropriate way to make a method which will accept a List/Collection of any enumeration?
For completeness, here's the rest of what I'm trying to do (these are static because they're in a shared utility class). These are completely untested yet (since I can't get past the compile error when calling the pack method), so take them with a grain of salt. And there might be a better way to do this, I'm doing this half to solve an interesting problem, and half because I think it is an interesting problem.
public static Int64 PackEnumList(List<Enum> listOfEnumValues) {
BitArray bits = new BitArray(64, defaultValue: false);
foreach (var value in listOfEnumValues) {
// get integer value of each Enum in the List:
int val = Convert.ToInt32(value);
if (val >= 64) {
// this enum has more options than we have bits, so cannot pack
throw new Exception("Enum value out of range for packing: " + val.ToString());
}
bits[val] = true;
}
var res = new Int64[1];
bits.CopyTo(res, 0);
return res[0];
}
// (this method is a little farther from the ideal: the resulting list will need
// to be matched by the caller to the appropriate List of Enums by casting
// each Int32 value to the Enum object in the list)
public static List<Int32> UnpackEnumList(Int64 packedValue) {
string binaryString = Convert.ToString(packedValue, 2);
List<Int32> res = new List<Int32>();
for (int pos = 0; pos < binaryString.Length; pos++) {
if (binaryString[binaryString.Length - pos - 1] == '1') {
// bit is on
res.Add(pos);
}
}
return res;
}
Is there a more appropriate way to make a method which will accept a List/Collection of any enumeration?
Within straight C#? Nope. But you can fudge it...
I have a project called Unconstrained Melody which allows you to make a generic method with a constraint of "T must be an enum type" or "T must be a delegate type". These are valid constraints at the IL level, but can't be expressed in C#
Basically Unconstrained Melody consists of two parts:
A library of useful methods with those constraints, where the source code is written using valid C# which doesn't actually represent those constraints, but uses a marker interface
An IL-rewriting project (ugly but servicable) which converts those constraints into the real "unspeakable" ones
(The expectation is that users of the library would just use the rewritten binary.)
It sounds like you could use the latter part of the project for your code here. It won't be terribly pleasant, but it would work. You might also find the library part useful.
As a side thought, you might want to consider using a [Flags]-style enum instead:
[Flags]
public enum Locations {
LocationA = 1 << 0,
LocationB = 1 << 1,
LocationC = 1 << 2
}
Change your method signature to public Int64 PackEnumList(IEnumerable<Enum> listOfEnumValues)
And then call it like following:
public Int64 PackedLocations
{
get { return PackEnumList(this._myLocations.Cast<Enum>()); }
}
A List<Enum> is not a List<Locations> nor a List<Int32>. Use a generic method to handle the list:
public static void PackEnumList<T>(IEnumerable<T> list) where T : IConvertible
{
foreach (var value in list)
int numeric = value.ToInt32();
// etc.
}
I'd change your signature method to:
public Int64 PackEnumList<T>(IEnumerable<T> listOfEnumValues) where T : struct, IFormattable, IConvertible {
...
}
The where T : struct... constrains it to enum types only (any any other struct implementing both interfaces, which is probably very low)

Can I use a reference inside a C# function like C++?

In C++ I can do this:
int flag=0,int1=0,int2=1;
int &iRef = (flag==0?int1:int2);
iRef +=1;
with the effect that int1 gets incremented.
I have to modify some older c# code and it would be really helpful if I could do something similar, but I'm thinking ... maybe not. Anybody?
UPDATE: The feature discussed below was finally added in C# 7.
The feature you want - to make managed local variable aliases is not supported in C#. You can do it with formal parameters - you can make a formal parameter that is an alias of any variable - but you cannot make a local which is an alias of any variable.
However, there is no technical difficulty stopping us from doing so; the CLR type system supports "ref local variables". (It also supports ref return types but does not support ref fields.)
A few years back I actually wrote a prototype version of C# which supported ref locals and ref return types, and it worked very nicely, so we have empirical evidence that we can do so successfully. However, it is highly unlikely that this feature will be added to C# any time soon, if ever. See http://ericlippert.com/2011/06/23/ref-returns-and-ref-locals/ for details.
I note that if I were you, I would avoid this in any language. Writing programs in which two variables share the same storage makes for code that is hard to read, hard to understand, hard to modify and hard to maintain.
See also the related question: Why doesn't C# support the return of references?
You can do it - or at least something very similar to what you want - but it's probably best to find another approach. For example, you can wrap the integers inside a simple reference type.
If you still want to do it, see the Ref<T> class posted by Eric Lippert here:
sealed class Ref<T>
{
private readonly Func<T> getter;
private readonly Action<T> setter;
public Ref(Func<T> getter, Action<T> setter)
{
this.getter = getter;
this.setter = setter;
}
public T Value { get { return getter(); } set { setter(value); } }
}
public class Program
{
public static void Main()
{
int flag=0,int1=0,int2=1;
Ref<int> iRef = (flag == 0 ?
new Ref<int>(() => int1, z => { int1 = z; }) :
new Ref<int>(() => int2, z => { int2 = z; }));
iRef.Value += 1;
Console.WriteLine(int1);
}
}
Output:
1
If all you need is to modify a value type within a function, then pass the parameter with the ref keyword.
int i = 0;
void increment(ref int integer)
{
integer++;
}
increment(ref i);
Yes you can do that with C# 7.0. It has support for returning references and storing references. See my answer here.
Fraid not. You could do it with unsafe code and pointers like so:
int flag=0,int1=0,int2=1;
unsafe
{
int *iRef = (flag==0? &int1:&int2);
*iRef +=1;
}
(not saying that's a good idea or anything :))
There is no direct equivelent in C#. There are a couple of options -
You can use unsafe code and pointers as suggested by dkackman.
Another alternative is to use a reference type (class) which holds the value. For exmaple:
// Using something like
public class Wrapped<T> {
public Wrapped(T initial) {
this.Value = initial;
}
public T Value { get; set; }
}
// You can do:
bool flag=false;
var int1 = new Wrapped<int>(0);
var int2 = new Wrapped<int>(1);
Wrapped<int> iRef = flag ? int2 : int1;
iRef.Value = iRef.Value + 1;
Since you're working with references to a class, the assignment to iRef copies the reference, and the above works...
You could use an Action delegate like this:
int flag = 0, int1 = 0, int2 = 0;
Action increment = flag == 0 ? (Action) (() => ++int1) : () => ++int2;
increment();

How to downcast a ref variable within the method

I need to downcast a long to an int in a method where the long is passed as a ref variable:
public void Foo(ref long l)
{
// need to consume l as an int
}
How can I easily do this?
You can't. However, any value you want to put into a ref int can be put into a ref long anyway - you've just got to worry about the initial value, and what you want to do if it's outside the range of int.
How many places do you need to write to the ref parameter or read it within your code? If it's only in one or two places, you should be okay just to cast appropriately at the right times. Otherwise, you might want to introduce a new method:
public void Foo(ref int x)
{
// Here's the body I *really* want
}
public void Foo(ref long x)
{
// But I'm forced to use this signature for whatever
// reasons. Oh well. This hack isn't an *exact* mimic
// of ref behaviour, but it's close.
// TODO: Decide an overflow policy
int tmp = (int) x;
Foo(ref tmp);
x = tmp;
}
The reason I say in the comments that it's not an exact mimic for the behaviour is that normally changes to the original ref parameter are visible even before the method returns, but now they'll only be visible at the very end. Also, if the method throws an exception, the value won't have been changed. The latter could be fixed with try/finally, but that's a bit clunky. In fact, if you want the try/finally behaviour you can do it all in a single method easily:
public void Foo(ref long x)
{
int y = (int) x;
try
{
// Main body of code
}
finally
{
x = y;
}
}
You don't. You can't take your reference and point it to a different type. How would the code calling your method know that it's changed?
If you just want to work with the value as an int, then you could do something like this:
private void Process(ref long l)
{
int i = (int)l;
// do whatever
}
You're a little light on the details, but if you're talking about this scenario:
public void Something(ref long something)
{
// code
}
int foo;
Something(ref foo);
try this:
long foo;
Something(ref foo);
int bar = (int) foo;
You can't safely cast a long to an int regardless of whether it's nullable or not as theres a chance it will overflow.
try this
if (!blah.HasValue)
blah = long.MaxValue;
int x = (int)blah.Value;
Console.WriteLine(x); //Not What you expect
You cannot directly cast this. The best option would be to cast it to a local, then assign it at the end of your method.
void Method(ref long myValue)
{
int tempValue = (int)myValue;
// change tempValue
myValue = tempValue;
}

Categories

Resources