question

Alice-2652 avatar image
0 Votes"
Alice-2652 asked karenpayneoregon answered

How to Validate array arguments and returning int

I'm improving my C# skills this last time by learning difficult stuff I found on the internet like TDD, Design Pattern, DDD and others... I discovered this exercise in an a book a friend of mine gave me, and I'm busy trying to to solve it.

So far below is my code but I'm not sure if I'm doing it right. Can you please assist?

 public class myValidateArgument
 {
    public int Validate(string[] args)
    {
      if(int.TryParse(args, out value))
      {
        // int value
      }
      else
      {
        // 
      }
    }
 }

Exercise to solve

Write a ValidateArguments class with a Validate( string[] args ), returning an int.

Make sure that it does not throw any exceptions! Arguments are passed through the Validate method, and each one of them is optional.

Example arguments:

string[] args = {"--name", "SOME_NAME", "--count", "10"};

Arguments are case−insensitive, for example --name and --NAME should have the same effect.

Values that can be returned by Validate are:

 −1 − user passed invalid data/arguments;
 0  − everything is ok;
 1  − user asked to print help information;

The user can pass the following three parameters:

 count − an integer between 10 and 100 (inclusive);
 name  − a string of length between 3 and 10 characters;
 help  − user asked to print help information.
 Although the help argument has a higher precedence, if other parameters are passed along with it, they must still be validated. If the parameters are valid, the function should return 1.

If an unrecognized argument or an empty array is passed, the function should return -1.

Example use case in the code:

 var val = new ValidateArguments();
 var result = val.Validate(args);






dotnet-csharp
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

1 Answer

karenpayneoregon avatar image
0 Votes"
karenpayneoregon answered

There are many assertions which need to be done as you have already guessed. Rather than provide a full example I will provider some ideas and helper methods with unit test methods.

For string test you need to assert case insensitive which is done in EqualsIgnoreCase() while ContainsIgnoreCase() is a generic method to see if an item is in an array. IsNull() to determine if an array is empty/null and ToIntegerArray() to get int from a string array.

 public static class Helpers
 {
     /// <summary>
     /// Case insensitive equals
     /// </summary>
     /// <param name="sender">The first string to compare, or null.</param>
     /// <param name="value">The second string to compare, or null</param>
     /// <returns>true if both strings are equal</returns>
     public static bool EqualsIgnoreCase(this string sender, string value) => 
         string.Equals(sender, value, StringComparison.OrdinalIgnoreCase);
    
     public static bool ContainsIgnoreCase(this string[] sender, string value) =>
         sender.Contains(value, StringComparer.OrdinalIgnoreCase);
    
     /// <summary>
     /// Test if array is null
     /// </summary>
     /// <typeparam name="T">Array type</typeparam>
     /// <param name="sender">Array to test if null</param>
     /// <returns>True if null, false if not empty/null</returns>
     public static bool IsNull<T>(this T[] sender) => !(sender?.Length > 0);
    
     public static int[] ToIntegerArray(this string[] sender)
     {
    
         var intArray = Array
             .ConvertAll(sender,
                 (input) => new
                 {
                     IsInteger = int.TryParse(input, out var integerValue),
                     Value = integerValue
                 })
             .Where(result => result.IsInteger)
             .Select(result => result.Value)
             .ToArray();
    
         return intArray;
    
     }
 }

Then write unit test methods where the following are starter test, not every possible test are shown, these are to give you an idea of what is needed. Once the test are good to go you can implement them in your application code minus the Asserts.

 [TestMethod]
 public void Examples1()
 {
     string[] values = {"--name", "--Name", "--NAME" };
     string param = "--name";
     Assert.IsTrue(values.All(item => item.EqualsIgnoreCase(param)));
    
     values[1] = "-name";
     Assert.IsFalse(values.All(item => item.EqualsIgnoreCase(param)));
 }
    
 [TestMethod]
 public void Examples2()
 {
     string[] args = { "--name", "SOME_NAME", "--count", "10" };
     Assert.IsTrue(args.Length == 4);
    
     Assert.IsTrue(args.ContainsIgnoreCase("--Name"));
    
     Array.Resize(ref args, 0);
     Assert.IsTrue(args.IsNull());
 }
    
 [TestMethod]
 public void Examples3()
 {
     string[] args = { "--help", "SOME_NAME", "--count", "10" };
     Assert.IsTrue(args.Length >0);
     Assert.IsTrue(args.ContainsIgnoreCase("--HELP"));
 }
 [TestMethod]
 public void Examples4()
 {
     string[] args = { "--help", "SOME_NAME", "--count", "10" };
     Assert.IsTrue(args.Length == 4);
     Assert.IsTrue(args.ContainsIgnoreCase("--count"));
 }
 [TestMethod]
 public void Examples5()
 {
     string[] args = { "--help", "SOME_NAME", "--count", "10" };
     Assert.IsTrue(args.ContainsIgnoreCase("--count"));
    
     var items = args.ToIntegerArray();
     Assert.IsFalse(items.IsNull());
     Assert.IsTrue(items.Length == 1 && items[0] == 10);
 }


An alternate path is data annotations. Although the following is done in a WPF project the code can be used in any type of project although ASP.NET is a tad different and more robust.


5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.