teadrinker
teadrinker
CC#
Created by teadrinker on 3/27/2024 in #help
Avoiding boxing (causing many small allocations) in generic classes
Can the compiler or runtime optimization avoid trivial boxing like (T)(object)? Example below (simplified, real case would have more types and more functionality which makes non-generic solution cause a lot of code duplication)
interface IValueWrap
{
void SetFloatValue(float v);
void SetValue(object v);
}
public class ValueWrap<T> : IValueWrap
{
public T val;
public void SetValue(object v)
{
val = (T)System.Convert.ChangeType(v, typeof(T));
}
public void SetFloatValue(float v)
{
// val = val switch
// {
// float f => v, // Error: Cannot implicitly convert type 'float' to 'T'
// _ => (T) System.Convert.ChangeType(v, typeof(T))
// };

// switch (val)
// {
// case float floatVal: val = v; break; // Error: Cannot implicitly convert type 'float' to 'T'
// default: SetValue(val); break;
// }

if (typeof(T) == typeof(float))
{
// val = v; // Error: Cannot implicitly convert type 'float' to 'T'
// val = (T) v; // Error: Cannot convert type 'float' to 'T'
// Set(v); // Error: ... There is no boxing conversion from 'float' to 'T'
val = (T)(object)v; // Works, but how can I avoid boxing/unboxing to object?
}
else
SetValue(v);
}
public void Set<T2>(T2 v) where T2 : T
{
val = v;
}
}
interface IValueWrap
{
void SetFloatValue(float v);
void SetValue(object v);
}
public class ValueWrap<T> : IValueWrap
{
public T val;
public void SetValue(object v)
{
val = (T)System.Convert.ChangeType(v, typeof(T));
}
public void SetFloatValue(float v)
{
// val = val switch
// {
// float f => v, // Error: Cannot implicitly convert type 'float' to 'T'
// _ => (T) System.Convert.ChangeType(v, typeof(T))
// };

// switch (val)
// {
// case float floatVal: val = v; break; // Error: Cannot implicitly convert type 'float' to 'T'
// default: SetValue(val); break;
// }

if (typeof(T) == typeof(float))
{
// val = v; // Error: Cannot implicitly convert type 'float' to 'T'
// val = (T) v; // Error: Cannot convert type 'float' to 'T'
// Set(v); // Error: ... There is no boxing conversion from 'float' to 'T'
val = (T)(object)v; // Works, but how can I avoid boxing/unboxing to object?
}
else
SetValue(v);
}
public void Set<T2>(T2 v) where T2 : T
{
val = v;
}
}
4 replies