none
Name String Format In C# 8.0 RRS feed

  • Question

  • I am having string with named parameter and params object[] values How can I create a string with thir respective object values based on name

    Eg. string input = "My Name is {name}"; //Value of name will come from params object[] values

     
    Tuesday, March 31, 2020 8:50 PM

All replies

  • Is this what you mean?

    public void UseParams(string name,params string[] list)
    {
        Console.WriteLine($@"{name} {list[0]} {list[1]}");
    }
    
    private void button1_Click(object sender, EventArgs e)
    {
        UseParams("Karen","Portland","Oregon");
    }

    Or

    public void UseParams(string name,params string[] list)
    {
        Console.WriteLine($@"{name} {list[0]} {list[1]}");
    }
    
    private void button5_Click(object sender, EventArgs e)
    {
        UseParams(list:new string[] { "Portland", "Oregon" }, name: "Karen");
    }


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange


    Tuesday, March 31, 2020 9:36 PM
    Moderator
  • No It wont work as I wanted Se below example, values can be of any type not string specific
    Func("My Name is {name} and Age is {age}",values);
    private void Func(string message, params object[] values)
    {
          var formattedMessage = //String Formatting;
    }
    

    Tuesday, March 31, 2020 9:43 PM
  • No It wont work as I wanted Se below example, values can be of any type not string specific
    Func("My Name is {name} and Age is {age}",values);
    private void Func(string message, params object[] values)
    {
          var formattedMessage = //String Formatting;
    }

    I added a second code sample and didn't use a Func because you didn't mention that.

    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    Tuesday, March 31, 2020 9:45 PM
    Moderator
  • No It wont work. As Values length may vary and Its of Object type and named parameter name can also vary.

    Name between {} can be considered as parameter

    Tuesday, March 31, 2020 9:50 PM
  • Greetings TA.

    Do you mean like this?

    string formattedMessage = string.Format("My Name is {0} and Age is {1}", values[0], values[1]);

    Wednesday, April 1, 2020 2:28 AM
  • Hi Tech Aspirant,

    Thank you for posting here.

    Do you mean this?

        class Program
        {
            static void Main(string[] args)
            {
                List<object> list = new List<object>();
                list.Add(new Class1() { ID = 1, Name = "Timon" });
                list.Add(new Class2() { Name="Tom",Age = 35});
    
                Func("Message", list.ToArray());
                Console.WriteLine("Press any key to continue...");
                Console.ReadKey();
            }
            private static void Func(string message, params object[] values)
            {
                var formattedMessage = message;//String Formatting;
                foreach (var item in values)
                {
                    formattedMessage += "\n";
                    PropertyInfo[] propertyInfos = item.GetType().GetProperties();
                    foreach (var property in propertyInfos)
                    {
                        formattedMessage = formattedMessage+ property.GetValue(item)+"\t";
                    }
                }
                Console.WriteLine(formattedMessage);
            }
        }
        class Class1
        {
            public int ID { get; set; }
            public string Name { get; set; }
        }
        class Class2
        {
            public string Name { get; set; }
            public int Age { get; set; }
        }

    Result:

    If there is still no response to your needs, please describe your problem in more detail.

    We don't quite understand what you mean.

    Best Regards,

    Timon


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Wednesday, April 1, 2020 3:23 AM
  • Maybe adopt this form or parameters:

    Func( "My Name is {name} and Age is {age}", new { name = "John", age = 92 } );

    Then implement Func.

    Wednesday, April 1, 2020 8:04 AM
  • No It wont work. As name and age are not fixed.

    Name can be dynamic any thing can come

    Wednesday, April 1, 2020 12:16 PM
  • A lot of people are posting answers and you keep saying wrong but aren't really clarifying exactly what you want with full samples of everything you're looking for. This isn't really helping anyone. Please provide code examples of exactly what you're looking for and ALL constraints you have. 

    To me it sounds like you are trying to use an arbitrary list of values determined at runtime. Therefore string interpolation ($) won't work as it is compile time (mostly). You are forced to use the same code that interpolation uses which is String.Format. That method accepts any # and type of arguments so there shouldn't be any issues there whatsoever.

    The only thing outstanding is the format string itself. You haven't provided any realistic examples yet so we have no way of knowing what you want. Let's start with your first example that posted as a reply.

    //Func("My Name is {name} and Age is {age}",values);
    //private void Func(string message, params object[] values)
    //{
      //    var formattedMessage = //String Formatting;
    //}
    
    //Don't need your own function but note you must use ordinals
    var formattedMessage = String.Format(message, values);

    Your second response: As Values length may vary and Its of Object type and named parameter name can also vary.

    Doesn't matter for String.Format. It accepts an array of objects and converts each one to a string using ToString.

    The biggest issue is that you must use ordinals. Since you're passing an array of values that array of values has no names in it. Therefore you cannot magically map `name` to a value because there is no way to know where the `name` value is in an array of objects.

    object[] values = new object[] {
       "Bob", 10, 4.6
    };
    
    //How exactly can you find "name" inside an object array of values???
    var message = "Hello {name}";
    
    

    You need to identify exactly how your code expects this to work. By itself it isn't possible. You could pass key-value pairs in or a single object and then use reflection to get the properties but that isn't the most performant code.

    Ultimately it looks like you're trying to use templated strings. There are already libraries available that can do that for you so I'd recommend you simply use them. But they are going to have the same problems as mentioned above. Given an array of objects there is no way to map them to named values as those names don't exist at runtime. You'll have to pass a single object (for reflection) or some structure that allows mapping of names to values. Without that your templating string doesn't work.

    You could also build your own template engine. It requires a reasonable amount of code (couple hundred of lines in my experience) but isn't difficult.


    Michael Taylor http://www.michaeltaylorp3.net

    Wednesday, April 1, 2020 1:14 PM
    Moderator
  • This is what I am trying to use as a work around

    string message = "My name is {name} and age is {age}";
    var count = 0;
          var visited = new List<Archive>();
          foreach (var item in values)
          {
            message = message.Replace(message.Split('{', '}')[startindex], (count).ToString());
            startindex = startindex + 2;
            count += 1;
          }
    string output = string.Format(message,values);
    Its working. Can I Optimize that ? First Index from values will be the value of first parameter. So If values and parameters may be dynamic and can be used In the above manner.

    Wednesday, April 1, 2020 6:06 PM
  • That is very inefficient and won't work right anyway. You are making an assumption that the message lists the substitution values in the order they appear in the array. You cannot enforce that. Furthermore you're making an assumption that those substitution names have any bearing on anything and aren't repeated. This message, for example, will fail:

    var message = "My name is {name}, is your name also {name}";

    To be honest, if you cannot properly implement string interpolation it would just be better to stick with ordinals. Otherwise you run the risk of the functionality being misused. The only way for someone to realize your formatting is not working, by design, would be to look at the code. Simple ordinals (which is what String.Format) does is cleaner and allows argument reuse.

    Another issue with your code is that you're enumerating through `values` which you never defined. You created a `visited` value but that isn't used in your code. But each time through your `foreach` loop you're trying to replace the format specifiers with the ordinal equivalent. But you're storing that back into the original message. Since you have a single message for all values you'd only want to do this once.  Let me explain this in an algorithm so it makes more sense.

    - Split the message on curly brace boundary
    - Grab the `startIndex` element (if any)
    - Replace everything to the left of the value with count??
    - Do this each time through the loop

    Again, I'm going to recommend that you either use regular ordinals like everybody is used to or you use a formal templating engine that is smart enough to map names to values. The piecemeal approach you have now isn't going to work long term for much of anything. It simply isn't smart enough for what people would expect.

    At a minimum you can build a simple templating engine that takes a message string like you have and an object (not an array). Then use a regular expression to break out the format specifiers in the string. Use reflection to grab the public properties of the provided object and then for each specifier use reflection to grab the corresponding property value from the object. With some caching, case sensitivity checks and decisions on missing properties you can get something to work in 100 or so lines of code to do what you want.

    var message = "My name is {name} and age is {age}";
    
    var person = new () { Name = "Bob", Age = 10 };
    
    //My name is Bob and age is 10
    var result = SomeTemplateEngine.Format(message, person);


    Michael Taylor http://www.michaeltaylorp3.net

    Wednesday, April 1, 2020 6:36 PM
    Moderator