How to convert to string an 'allows ref struct' generic argument?

19 hours ago 3
ARTICLE AD BOX

The proposal for allos ref struct doesn't explicitly cover how to call object methods.

However, looking at a similar generic method;

public string? Method<T>(T arg) where T : struct => arg.ToString();

Results in the IL sequence constrained, callvirt. For the constrained opcode;

... when method was defined on Object, ValueType, or Enum and not overridden by thisType ... then ptr is dereferenced, boxed, and passed as the 'this' pointer to the callvirt method instruction

But;

You can't box a ref struct to ValueType or Object.

So this clearly isn't supported for a ref struct type. Which explains your implicit conversion error, even if this behaviour isn't explicitly documented anywhere else.

Instead you could require that all type arguments implement IFormattable;

public string? Method<T>(T arg) where T : IFormattable, allows ref struct => arg.ToString(null, CultureInfo.CurrentCulture);

Which should be equivalent to how $"{arg}" would otherwise be compiled. If DefaultInterpolatedStringHandler supported ref struct at least.

Or introduce your own, similar interface, and force all callers to implement it.

Jeremy Lakeman's user avatar

4 Comments

Thanks Jeremy, this trick can be useful. Unfortunately in my case most of the time the T will be either string or ReadOnlySpan<char>, and neither of those types implements the IFormattable interface.

2026-02-18T05:20:08.337Z+00:00

Which just leaves method overloading, which might be a better idea anway.

2026-02-18T05:23:48.007Z+00:00

I am accepting your answer though, because it includes a solid explanation for why it's not possible to do what I want to do.

2026-02-18T05:22:38.577Z+00:00

In my case I can't do method overloading either, because the T is defined on the enclosing type, not on the Method. Sorry for presenting an inaccurate demo of my actual use case. I was overzealous at simplifying the demo. :-)

2026-02-18T05:26:52.63Z+00:00

I will assume that T overrides object.ToString, otherwise calling ToString must involve boxing, which you are not allowed to do to a ref struct.

One idea I thought of is to create a custom delegate with allows ref struct constraint like this:

delegate string StructToString<T>(ref T self) where T: allows ref struct;

Then Delegate.CreateDelegate can be used to create such a delegate from the MethodInfo of the ToString method.

void Method<T>(T arg) where T: struct, allows ref struct { var toStringMethod = typeof(T).GetMethod("ToString")!; var del = (StructToString<T>)Delegate.CreateDelegate(typeof(StructToString<T>), toStringMethod); Console.WriteLine(del(ref arg)); }

However, this only works if T is a value type. You would need a separate method with a different name for where T: class.

Sweeper's user avatar

1 Comment

This is very clever Sweeper, thanks! Unfortunately in my case the generic parameter T is defined in the enclosing type, and the Method is a member without generic parameters. So I can't use this trick.

2026-02-18T05:12:28.093Z+00:00

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.

Read Entire Article