简体   繁体   中英

How to combine extension method's this with params keyword?

I'd like to write an extension method:

static public bool IsKeyPressedAny(this params System.Windows.Input.Key[] keys)
{
    foreach (var key in keys)
    {
        if (System.Windows.Input.Keyboard.IsKeyDown(k))
        {
            return true;
        }
    }
    return false;
}

to be used like this

IsKeyPressedAny(Key.LeftShift, Key.RightShift);

or

IsKeyPressedAny(Key.a)

But the method's signature is invalid, adding this before params causes error CS1104: "A parameter array cannot be used with 'this' modifier on an extension method".

My current workaround is

static public bool IsKeyPressedAny(
    this System.Windows.Input.Key key
    , params System.Windows.Input.Key[] keys
)
{
    if (System.Windows.Input.Keyboard.IsKeyDown(key)) return true;

    foreach (var k in keys)
    {
        if (System.Windows.Input.Keyboard.IsKeyDown(k))
        {
            return true;
        }
    }
    return false;
}

which strikes me as a bit clunky. Is there a way to keep the benefits of using params while avoiding duplication of the argument type in the signature?

(kind of a) Solution

The comments made me realize I was missusing this . Since this is added as a method to the type it preceeds in the signature, using it before params is nonsense. I was trying to avoid typing the name of the class containing the method, this is not the way to solve that.

Consider to give the class a useful, somewhat specific name to get a nice syntax like this:

KeyPressed.Any(Key.LeftShift, Key.RightShift);

Is implemented by

public static class KeyPressed
{
    public static bool Any(params System.Windows.Input.Key[] keys)
    {
        ....
    }
}

Well, this doesn't really answer your question, but could still be a useful solution.

this adds the method to the type it preceeds in the signature, using it before params makes no sense.

this is not intended to save you typing the class' name containing the method.

What you are looking for is called "using static", it imports things just like a regular using directive for namespaces:

using static YourNameSpace.KeyHelpers;

will allow you to call YourNameSpace.KeyHelpers.IsKeyPressedAny by just it's name, without the class name:

IsKeyPressedAny(Key.LeftShift, Key.RightShift);

Example:

public static class KeyHelpers
{
    public static bool IsKeyPressedAny(params System.Windows.Input.Key[] keys)
    {
        foreach (var key in keys)
        {
            if (System.Windows.Input.Keyboard.IsKeyDown(k))
            {
                return true;
            }
        }
        return false;
    }
}

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