简体   繁体   中英

Generic method arguments

I have a method that accepts string[] arguments

public static void MyMethod(string[] s1, string[] s2, string[] s3, string[] s4)
{

}

Sometimes I have the situation that instead of string[] I would like to use a normal string

Is it possible to set the method's generic arguments to accept either an array or plain text?

What I need (examples):

MyMethod(["a", "b"], ["s", "m"], ["i", "k"], ["a", "e"])
MyMethod(["a", "p"], "u", ["v", "p"], "e")
MyMethod("a", "b", "b", "d")

and other combinations

You can use the params keyword:

public static void MyMethod(params string[] s)
{

}

With this way you can either pass a simple string as a parameter to your method like this:

MyMethod("str");

Or multiple values as array:

MyMethod("str1","str2","str3");

Based on your desired result in your updated question, you might find the following implementation also useful:

public static void MyMethod(params string[][] s)
{

}

This will works for all of the samples which you've mentioned in the What I need section of your question.

Interesting. What you need is as per others said using params with an indirection / custom type supporting implicit conversion from both string and string[] .

For example:

public static void MyMethod(params StringArray[] s)
{   
}

class StringArray
{
    public string[] Value { get; set; }

    public static implicit operator StringArray(string str)
    {
        return new StringArray
        {
            Value = new[] { str }
        };
    }

    public static implicit operator StringArray(string[] str)
    {
        return new StringArray
        {
            Value = str
        };
    }
}

Then you can do:

MyMethod(new[] { "a", "b" }, new[] { "s", "m" }, new[] { "i", "k" }, new[] { "a", "e" });
MyMethod(new[] { "a", "p" }, "u", new[] { "v", "p" }, "e");
MyMethod("a", "b", "b", "d");

You can try to use params with jagged array for that

public static void MyMethod(params string[][] s1)
{
}

and update a method invocation a little bit

MyMethod(new[] { "a", "b" }, new[] { "s", "m" });
MyMethod(new[] { "a", "p" }, new[] { "u" }, new[] { "v", "p" }, new[] { "e" });
MyMethod(new[] { "a", "b", "b", "d" });

Please, keep in mind that in last line you are passing just a one-dimension array and you should properly manage it inside a method

However, it doesn't look readable enough, IMO. It's better to have a few overloads with different signatures

public static void MyMethod(params string[][] s1)
{
}
public static void MyMethod(params string[] s1)
{
}

Then you can have the last method call as MyMethod("a", "b", "b", "d"); , without array declaration.

Unfortunately, you can't avoid using an array declaration with new operator, target-typed new expression will come in the next version of C#

It is possible with wrapper type and implicit operator. Optionally you can add property IsCollection to check how the wrapper was initialized.

class Program
{
    static void MyMethod(StringCollection s1, StringCollection s2, StringCollection s3, StringCollection s4)
    {

    }

    static void Main(string[] args)
    {
        MyMethod("a", "b", "c", "d");
        MyMethod(new[] { "a1", "a2" }, "b", "c", "d");
    }
}

class StringCollection
{
    public readonly bool IsCollection;
    public string[] Values;

    public StringCollection(string value)
    {
        Values = new[] { value };
        IsCollection = false;
    }

    public StringCollection(string[] values)
    {
        Values = values;
        IsCollection = true;
    }

    public static implicit operator StringCollection(string value)
    {
        return new StringCollection(value);
    }

    public static implicit operator StringCollection(string[] values)
    {
        return new StringCollection(values);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM