简体   繁体   中英

C# Delegate as object

Disclaimer: the unit-test related info for this question is not really relevant - you can skip to "The Problem" if you're not familiar with this, but it helps set the context.

I have a class that I need to unit-test. It looks like this:

public class NumberParser {
    public static void CheckByteRange(string str){...}
    [...]
    public static void CheckFloatRange(string str){...}
    [...]
}

I want to use an NUnit parametrized unit-test to test all these methods. Here's the test method:

    [TestCaseSource("CheckRange_Overflow_Inputs")]
    public void CheckRange_Overflow(string value, Action<string> method)
    {
        Assert.Throws<Exception>(() => method(value));
    }

The test uses TestCaseSourceAttribute to specify a field that contains a list of sets of arguments to the test method.

Now, NUnit expects a field called CheckRange_Overflow_Inputs , of type object[] , that itself contains object[] elements, each of which contains values for the arguments to the test method.

The problem:

Ideally, I'd like to write the field like this:

    private static readonly object[] CheckRange_Overflow_Inputs
        = new object[]
              {
                  new object[]{byte.MaxValue,  NumberParser.CheckByteRange },
                  [...]
                  new object[]{float.MaxValue, NumberParser.CheckFloatRange },
                  [...]
              };

But the compiler complains it can't cast a method group to an object.

That makes sense - NumberParser.CheckByteRange could be ambiguous, eg it could be overloaded.

But how can I get the compiler to allow me to save (as an object) the method called NumberParser.CheckByteRange that takes a string and returns void ?

What I tried (and failed succeeded):

 [...]
 new object[]{byte.MaxValue, (Action<string>)NumberParser.CheckByteRange },
 [...]

If the method was static , then your attempt would have worked. It can't work simply as

(Action<string>)NumberParser.CheckByteRange

when CheckByteRange is an instance (non- static ) method because you haven't told it which instance ( this ) to use. So either:

  • make CheckByteRange into a static method
  • tell it which instance to use, ie (Action<string>)someInstance.CheckByteRange

With them static , the following compiles fine for me:

private static readonly object[] CheckRange_Overflow_Inputs
    = new object[]
          {
              new object[]{byte.MaxValue,  (Action<string>) NumberParser.CheckByteRange },
              new object[]{float.MaxValue, (Action<string>) NumberParser.CheckFloatRange },
          };

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