Home > front end >  c# - can one pass parameters by value or as an object to function w/o overloading it
c# - can one pass parameters by value or as an object to function w/o overloading it

Time:02-05

In c# is there a way to create (or call) a function that accepts discreet parameters or an object of those parameters with out overloading it?

like:

function void foo(string a, string b, int c)
{
...
}

class boo{
  public string x {get;set;}
  public string y {get;set;}
  public int z {get;set;}
}

and then one could call it either way:

foo("asdf", "asdf", 1);

//or:

var zz = new boo(){x="asdf", y="asdf", z=1};
foo(zz);

I feel like we could do this in ColdFusion, which was precompiled I believe, by passing structs into functions... it was super handy for logging purposes (you could log the input by serializing the struct instead of creating a string with all the parameters values for logging... )

CodePudding user response:

That depends on why you don't want to use an override.

If the reason is that the function is in a library that you can't change, then the answer is yes, actually! You can create a lambda function that calls the original function by parsing the values from the object, and then pass that lambda to wherever it needs to go.

But if you don't want to write the override because it is too verbose for it's doing (and you would prefer to use something like the spread operator from JS), then you are out of luck, the lambda is just as verbose as the override.

CodePudding user response:

Solution without override

You can try using combination of params, selection and reflection concepts assuming that:

  • basic types such numbers, chars or strings are processed as is,
  • all properties are extracted from classes and their values are processed by one of two ways (see below for details).
static class Program
{
    static void Main()
    {
        foo("qwerty", "asdf", 1);
        var zz = new boo() { x = "abc", y = "xyz", z = 2 };
        foo(zz);
    }

    class boo
    {
        public string x { get; set; }
        public string y { get; set; }
        public int z { get; set; }
    }

    static void foo(params object[] values)
    {
        foreach (object value in values)
        {
            Type type = value.GetType();
            if (type.IsPrimitive // For char, int, double, etc.
                || type == typeof(string)) // It's crutch for string because 
                                           // string is not primitive type, 
                                           // but should be handled here. 
                                           // Who can improve it?
            {
                // Place here instructions like foo(string a, string b, int c)
                Console.WriteLine(value   " \thas been handled");
            }
            // ... Place here additional checks.
            else // For types that have properties (like your class boo).
            {
                try 
                {
                    foreach (PropertyInfo property in type.GetProperties())
                    {
                        var propertyValue = property.GetValue(value, index: null);
                        /* W A R N I N G ! ! !                              */
                        /* Choose and leave ONLY one of 2 ways as necessary */

                        /*       Fisrt way      */
                        // Place here instructions like foo(zz)
                        Console.WriteLine(propertyValue   "\thas been handled");

                        /*        - or -        */

                        /*      Second way      */
                        // Just pass it recursively:
                        foo(propertyValue);
                        // This method is better in that it processes 
                        // the entire tree of nested properties.
                    }
                }   
                catch
                {
                    // On error there is nothing to do.
                }
            }
        }
    }
}

The console output for this example looks like this:

qwerty  has been handled
asdf    has been handled
1       has been handled
abc     has been handled
xyz     has been handled
2       has been handled

Of course, this example is not for all occasions, but for your purposes it will do. You can add some checks for certain types in foo like DateTime, TimeSpan, etc:

else if (value is IConvertible convertible)
{
    // place here instructions like foo(IConvertible c)
    Console.WriteLine(convertible.ToString(CultureInfo.CurrentCulture) 
        "\thas been handled");
}
else if (value is IFormattable formattable)
{
    // place here instructions like foo(IFormattable f)
    Console.WriteLine(formattable.Format(null, CultureInfo.CurrentCulture) 
        "\thas been handled");
}
  •  Tags:  
  • Related