14

I have started to use Interpolated Strings (new feature of C# 6) and it is really useful and gracefully. But according to my needs I have to pass format of string to a method as a parameter. Something like next:

MyMethod(string format) 

In the past, I used it in the next way:

MyMethod("AAA{0:00}") 

Now I tried this code:

MyMethod($"AAA{i:00}") 

But this doesn't work, because i is created inside of the method and is out of scope in this context.

Is it possible to use any trick for passing interpolated strings as a parameter to a method?

0

4 Answers 4

10

You cannot do that, and that would not be a very good idea either - it means you are using local variables from another method.
This would defeat the purpose of this feature - to have compiler verifiable string interpolation and binding to local variables.

C# has several good alternatives. For example, using a Func:

public void MyMethod(Func<int,string> formatNumber) { int i = 3; var formatted = formatNumber(i); } 

use as:

MyMethod(number => $"AAA{number:00}"); 

This is better than what you have today - where you have the format string(s?) and its usage in different places.

If you have more than a single variable this approach can scale, but consider grouping them into a class (or a struct) - the func will look much better, and your code will be more readable. This class can also override .ToString(), which might be useful for you.

Another simple option is to pass just the format: MyMethod("00") and i.ToString(format), but that only works in your presumably simplified example.

Sign up to request clarification or add additional context in comments.

5 Comments

I mark this answer as most reasonable. But I am not going to use this solution. I am trying to keep my code simple and clear for understanding but this solution is too sophisticated. The best answer is in first part - I can't do it.
@RredCat I find this solution simple and easy to use. Why are you saying it's too complicated? Because it uses a lambda?
@svick Yes. Personally I love lambda but my real method has more than three parameters. In this case method's call will look strange, not clear and too long. (something like MyMethod(param0, param1, param2, lambda)).
@RredCat Are you worried about the method declaration or when it is called? I personally would prefer a call that reads param2, number => "AAA{number}" instead of param2, "AAA{0}", especially when there are multiple format parameters. It prevents mistakes and is more readable. As to the method declaration: you could create a delegate, which is much more concise than a Func parameter and callers can still use lambda notation. (e.g. MyFormat format instead of Func<long, int, string> format)
@enzi I had other parameters in this method and it looked to long with lambda. So I kept to use old style formatting in my case. But I like this MyMethod(number => $"AAA{number:00}"); approach as well.
9

There are several ways you can do this.

The first one is to add another method overload that takes a FormattableString (a new typed used by one of the variants of string interpollation) and calls the original one:

public void MyMethod(FormattableString fs) { MyMethod(fs.Format); } 

And you also have access to the arguments if you need to.

If you only need the format, just create an extension method to extract it:

public static string AsFormat(FormattableString fs) { return fs.Format; } 

5 Comments

I don't think this will work, since "i is created inside of the method".
I found the whole question a bit odd. I was just showing a way to get the format string out of an interpolated string.
@svick Note this is the solution here, but you need to use FormattableString all the way down (it captures the parameters necessary to complete the formatting).
@Richard, it captures the values. How they got there (parameters, method variables, type fields, etc.) is lost.
I don't know if this answers the original question, but this is a great way to delay interpolation of the string. Great for use in conditional logging, etc.
1

Several years since this was asked however I came across this via Google while searching for an answer that I already had in my head, but couldn't get my mind around the implementation/syntax.

My solution is further to what @Kobi supplied...

public class Person { public int Id {get; set;} public DateTime DoB {get;set;} public String Name {get;set;} } public class MyResolver { public Func<Person, string> Resolve {get;set;} public string ResolveToString<T>(T r) where T : Person { return this.Resolve(r); } } // code to use here... var employee = new Person(); employee.Id = 1234; employee.Name = "John"; employee.DoB = new DateTime(1977,1,1); var resolver = new MyResolver(); resolver.Resolve = x => $"This person is called {x.Name}, DoB is {x.DoB.ToString()} and their Id is {x.Id}"; Console.WriteLine(resolver.ResolveToString(employee)); 

I haven't tested the above for syntax errors but hopefully you get the idea and you can now just define "how" you want the string to look but leave the blanks to be filled in at runtime depending upon the values in your Person object.

Cheers,

Wayne

Comments

0

It is not possible. But the alternate way is

public static string MyMethod(string format, params object[] args) { if (format == null || args == null) throw new ArgumentNullException(format == null ? "format" : "args"); return string.Format((IFormatProvider) null, format, args); } 

EDIT:

MyMethod("The number is {0}", 12); 

EDIT2:

public static string MyMethod(string format) { var i = 12; var result = string.Format(null, format, i); return result; } MyMethod("{0:000}"); 

2 Comments

This does work, but if I understand the question correctly, 12 comes from within MyMethod, not from the calling function. Also, what are the benefits over using String.Format directly?
You can use args as i in that method instead of i from calling side but need to remove args parameter.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.