consider this cod here:
public ref struct RefValue <T> where T : unmanaged
{
public ref readonly T Item1;
public RefTuple(ref T item1)
{
Item1 = ref item1;
}
}
//This function gets a 'ref' directly to the dictionary value
//and 'RefValue<T>' is a ref-struct which has a 'ref readonly field T'
//to store args passed as 'ref param'
public RefValue<Stats> GetStatsByType(TileType t)
{
return new RefValue<Stats>(ref CollectionsMarshal.GetValueRefOrAddDefault(_typeStats, t, out _));
}
//THIS LINE HERE:!
//says: CS 1612: The return value is not a variable and therefore cannot be changed
public ref readonly Stats ExampleAsRef => ref GetStatsByType(TileType.Blue).Item1;
I don't understand why... I am keeping everything in sync/aligned, like:
the property returns ref readonly, the function returns ref readonly, the 'T' value of 'RefValue' is ref readonly, how does it come that he does want to accept that, I don't legit understand :/
Would be super cool if some1 has an answer to this, I do not..
Best regards
Stats is a simple struct, with some primitive fields.
PS: am using .NET 7 RC2, mac OS X 10.15, C#11
PS2:
here the missing types:
public struct Stats
{
/// <summary>
/// Count-Clicks, with maxTime inbetween them
/// </summary>
public int? Click;
public int? Swaps;
public int? Match;
public int? RePainted;
public int? Destroyed;
public Stats()
{
Destroyed = 0;
Click = 0;
Swaps = 0;
Match = 0;
RePainted = 0;
}
}
public enum TileType : short
{
Red, Blue, Green, Purple, Violet,
Length = Violet + 1, Empty = -1,
}
I also tried this, without any success as well:
public ref readonly Stats GetStatsByType(TileType t)
{
return ref (new RefTuple<Stats>(ref CollectionsMarshal.GetValueRefOrAddDefault(TypeStats, t, out var existedB4))).Item1;
}
private string GetShortName(string LongName)
{
string ShortFileName = new string('\0', 67);
**int Result = Support.PInvoke.SafeNative.kernel32.GetShortPathName(ref LongName, ref ShortFileName, ((ShortFileName) is null) ? 0 : Convert.ToString(ShortFileName).Length);**
ShortFileName = StringsHelper.GetFixedLengthString(ShortFileName, 67);
return ShortFileName.Substring(0, Math.Min(Result, ShortFileName.Length));
}
The above line throws a error "cannot implicitly convert type void to int"
GetShortPathName comes from Kernel32.dll that is wrapped in a class file as
public static void GetShortPathName(ref string lpszLongPath, ref string lpszShortPath, int cchBuffer);
Is there is any alternative to get it in int result?
GetShortPathName should return a uint, not be void:
public static uint GetShortPathName(...)
If you don't have control over Support.PInvoke.SafeNative.kernel32 then you'll need to create a new wrapper around the kernel call that does return the uint.
This question already has answers here:
Why doesn't returning by ref work for elements of collections?
(2 answers)
Closed 5 years ago.
While learning c# 7, I happen to stumble on Ref return. The GetSingle method below works as I learned which return me a reference outside. But GetIns method throws me out with a compile-time error. Unfortnately, I can't workout why and how these GetIns different from GetSingle. Can someone explain me?
Error: An expression cannot be used in this context because it may not be return by reference.
Please note one of the comment was proposing this as a duplicate. But that question was type of collection and this was specifically between member of a collection and a property in a type. Hence I see this as a different question
class Pro
{
static void Main()
{
var x = GetSingle(new int[] { 1, 2 });
Console.WriteLine(x);
}
static ref int GetSingle(int[] collection)
{
if (collection.Length > 0) return ref collection[0];
throw new IndexOutOfRangeException("Collection Parameter!");
}
static ref int GetIns(Shape s)
{
if (s.Area <= 0)
{
s.Area = 200;
return ref s.Area;
}
return ref s.Area;
}
struct Shape {public int Area{ get; set; }
}
This happens because Shape has a property Area and not a public int field member. You can not return references to properties.
This wont compile:
class Shape
{
private int mArea;
public int Area => mArea;
}
static ref int GetIns(Shape s)
{
if (s.Area <= 0)
{
s.Area = 200;
return ref s.Area;
}
return ref s.Area;
}
But this will:
class Shape
{
public int Area;
}
static ref int GetIns(Shape s)
{
if (s.Area <= 0)
{
s.Area = 200;
return ref s.Area;
}
return ref s.Area;
}
I am trying to map a ulong to a long (and vice-versa), and a uint to a int (and vice-versa), as shown below - in order to save the values in a MS-SQL-database with signed types integer and biginteger only.
I do this because I have to check (in the database) whether a number (uint, ulong) is within which range in a bunch of uint/ulong ranges (IPs - v4 & v6; actually the ulong is in reality a uint128 composed of two ulongs).
Is there a more efficient way to accomplish this than the code I have here:
public static ulong SignedLongToUnsignedLong(long signedLongValue)
{
ulong backConverted = 0;
// map ulong to long [ 9223372036854775808 = abs(long.MinValue) ]
if (signedLongValue < 0)
{
// Cannot take abs from MinValue
backConverted = (ulong)System.Math.Abs(signedLongValue - 1);
backConverted = 9223372036854775808 - backConverted - 1;
}
else
{
backConverted = (ulong)signedLongValue;
backConverted += 9223372036854775808;
}
return backConverted;
}
public static long UnsignedLongToSignedLong(ulong unsignedLongValue)
{
// map ulong to long [ 9223372036854775808 = abs(long.MinValue) ]
return (long) (unsignedLongValue - 9223372036854775808);
}
public static int UnsignedIntToSignedInt(uint unsignedIntValue)
{
// map uint to int [ 2147483648 = abs(long.MinValue) ]
return (int)(unsignedIntValue - 2147483648);
}
public static uint SignedIntToUnsignedInt(int signedIntValue)
{
uint backConverted = 0;
// map ulong to long [ 2147483648 = abs(long.MinValue) ]
if (signedIntValue < 0)
{
// Cannot take abs from MinValue
backConverted = (uint)System.Math.Abs(signedIntValue - 1);
backConverted = 2147483648 - backConverted - 1;
}
else
{
backConverted = (uint)signedIntValue;
backConverted += 2147483648;
}
return backConverted;
}
public static void TestLong()
{
long min_long = -9223372036854775808;
long max_long = 9223372036854775807;
ulong min_ulong = ulong.MinValue; // 0
ulong max_ulong = ulong.MaxValue; // 18446744073709551615 = (2^64)-1
long dbValueMin = UnsignedLongToSignedLong(min_ulong);
long dbValueMax = UnsignedLongToSignedLong(max_ulong);
ulong valueFromDbMin = SignedLongToUnsignedLong(dbValueMin);
ulong valueFromDbMax = SignedLongToUnsignedLong(dbValueMax);
System.Console.WriteLine(dbValueMin);
System.Console.WriteLine(dbValueMax);
System.Console.WriteLine(valueFromDbMin);
System.Console.WriteLine(valueFromDbMax);
}
public static void TestInt()
{
int min_int = -2147483648; // int.MinValue
int max_int = 2147483647; // int.MaxValue
uint min_uint= uint.MinValue; // 0
uint max_uint = uint.MaxValue; // 4294967295 = (2^32)-1
int dbValueMin = UnsignedIntToSignedInt(min_uint);
int dbValueMax = UnsignedIntToSignedInt(max_uint);
uint valueFromDbMin = SignedIntToUnsignedInt(dbValueMin);
uint valueFromDbMax = SignedIntToUnsignedInt(dbValueMax);
System.Console.WriteLine(dbValueMin);
System.Console.WriteLine(dbValueMax);
System.Console.WriteLine(valueFromDbMin);
System.Console.WriteLine(valueFromDbMax);
}
Option 1: order-preserving map
It sounds like you're asking for a map which preserves order, meaning that, for example, if x and y are ulongs and x < y, then MapUlongToLong(x) < MapUlongToLong(y).
Here's how to do that:
To map from ulong to long, cast and add long.MinValue. To map from long back to ulong, subtract long.MinValue and cast. In either case, use an unchecked context so that overflow conditions are ignored.
public static long MapUlongToLong(ulong ulongValue)
{
return unchecked((long)ulongValue + long.MinValue);
}
public static ulong MapLongToUlong(long longValue)
{
return unchecked((ulong)(longValue - long.MinValue));
}
The logic for uint and int is exactly analogous.
(Option 1 is the original answer I wrote in 2016. I added option 2, and the comparison of the two, in 2021.)
Option 2: non-order-preserving map
I don't think this is what you're asking for, but it's even easier to do the conversion if you don't care about preserving order.
These functions work the same way as the above functions, except that we don't bother to add or subtract long.MinValue.
public static long MapUlongToLong(ulong ulongValue)
{
return unchecked((long)ulongValue);
}
public static ulong MapLongToUlong(long longValue)
{
return unchecked((ulong)longValue);
}
Which option is better?
Option 1 preserves order and option 2 doesn't, so if you need to preserve order, use option 1.
How long do the functions in option 1 take to execute? Well, those functions will probably be inlined and optimized by the JIT compiler, and they're ultimately asking the CPU to do something very, very simple. I'm guessing that each function call will take less than 1 nanosecond.
One of the comments describes this less-than-a-nanosecond execution time as being "relatively slow." If a nanosecond is too slow for you, you may want to use option 2.
The functions in option 2 will also probably be inlined and optimized by the JIT compiler, and it turns out that as far as the CPU is concerned, those functions do literally nothing. Therefore, no machine code will be generated for those functions, and so each function call will take no time at all—in other words, 0 nanoseconds.
Aron's answer does the same thing as option 2, and I'm guessing that it will run equally fast, too.
Althought Tanner Swett is correct. A much nicer and dirty solution is to tell .net to map access for a ulong to the same memory address as a long. This will give you instantaneous conversion speed.
void Main()
{
var foo = new Foo { Long = -1 };
Console.WriteLine(foo.ULong);
}
// Define other methods and classes here
[StructLayout(LayoutKind.Explicit)]
public class Foo
{
[FieldOffset(0)]
private ulong _ulong;
[FieldOffset(0)]
private long _long;
public long Long
{
get { return _long; }
set { _long = value; }
}
public ulong ULong
{
get { return _ulong; }
set { _ulong = value; }
}
}
By setting your entity framework POCO to use the attributes shown, you can control the memory addresses that the fields are mapped to.
Therefore, no conversion ever occurs.
This code is 100% faster than Tanner Swett's.
Necromancing.
Generic answer based on the answer of Tanner Swett:
private static class Number<T>
{
private static object GetConstValue(System.Type t, string propertyName)
{
System.Reflection.FieldInfo pi = t.GetField(propertyName, System.Reflection.BindingFlags.Static
| System.Reflection.BindingFlags.Public
| System.Reflection.BindingFlags.NonPublic
);
return pi.GetValue(null);
}
private static T GetMinValue<T>()
{
return (T)GetConstValue(typeof(T), "MinValue");
}
private static T GetMaxValue<T>()
{
return (T)GetConstValue(typeof(T), "MaxValue");
}
private static System.Func<T, T, T> CompileAdd<T>()
{
// Declare the parameters
System.Linq.Expressions.ParameterExpression paramA =
System.Linq.Expressions.Expression.Parameter(typeof(T), "a");
System.Linq.Expressions.ParameterExpression paramB =
System.Linq.Expressions.Expression.Parameter(typeof(T), "b");
// Add the parameters
System.Linq.Expressions.BinaryExpression body =
System.Linq.Expressions.Expression.Add(paramA, paramB);
// Compile it
System.Func<T, T, T> add =
System.Linq.Expressions.Expression.Lambda<System.Func<T, T, T>>
(body, paramA, paramB).Compile();
return add;
}
private static System.Func<T, T, T> CompileSubtract<T>()
{
// Declare the parameters
System.Linq.Expressions.ParameterExpression paramA =
System.Linq.Expressions.Expression.Parameter(typeof(T), "a");
System.Linq.Expressions.ParameterExpression paramB =
System.Linq.Expressions.Expression.Parameter(typeof(T), "b");
// Subtract the parameters
System.Linq.Expressions.BinaryExpression body =
System.Linq.Expressions.Expression.Subtract(paramA, paramB);
// Compile it
System.Func<T, T, T> subtract =
System.Linq.Expressions.Expression.Lambda<System.Func<T, T, T>>
(body, paramA, paramB).Compile();
return subtract;
}
public static T MinValue = GetMinValue<T>();
public static T MaxValue = GetMaxValue<T>();
public static System.Func<T, T, T> Add = CompileAdd<T>();
public static System.Func<T, T, T> Subtract = CompileSubtract<T>();
}
public static TSigned MapUnsignedToSigned<TUnsigned, TSigned>(TUnsigned ulongValue)
{
TSigned signed = default(TSigned);
unchecked
{
signed = Number<TSigned>.Add((TSigned)(dynamic)ulongValue, Number<TSigned>.MinValue);
}
return signed;
}
public static TUnsigned MapSignedToUnsigned<TSigned, TUnsigned>(TSigned longValue)
{
TUnsigned unsigned = default(TUnsigned);
unchecked
{
unsigned = (TUnsigned)(dynamic) Number<TSigned>
.Subtract(longValue, Number<TSigned>.MinValue);
}
return unsigned;
}
equivalent:
// return MapUnsignedToSigned<ulong, long>(ulongValue);
private static long MapULongToLong(ulong ulongValue)
{
return unchecked((long)ulongValue + long.MinValue);
}
// return MapSignedToUnsigned<long, ulong>(longValue);
private static ulong MapLongToUlong(long longValue)
{
return unchecked((ulong)(longValue - long.MinValue));
}
I know that a property can be set as a single type and not to be changed once set, but is there a way to create a property or a property-like object that sets an int while returns a string?
I'm constantly creating variables like an int which will later on be used as string only and never to be used as int once set. So in that case i would always have to make a lot of conversions considering that it's not just one type to another.
Maybe something like
struct strint
{
private int i; // 0 by default
public static implicit operator strint(int value) {
return new strint { i = value };
}
public static implicit operator string(strint value) {
return value.i.ToString();
}
public static implicit operator int(strint value) {
return value.i;
}
}
Sample use:
strint a = 1;
a += 2; // 3
int i = a; // 3
string s = a; // "3"
When you need it only as a string and only once as integer (during initialization) go with the string-value:
int readonly _myProp;
string MyProp { get { return _myProp.ToString(); } }
MyClass(int theValue
{
this._myProp = theValue;
}
The readonly moreover ensures that a user can only set the value during intialization of your class.