How do I distinguish between two methods with the same name and number of parameters in a generic class?

后端 未结 2 1763
情歌与酒
情歌与酒 2021-01-20 14:46

Here\'s my class:

public class MyClass
{
    public void MyMethod(T a)
    {
    }

    public void MyMethod(int a)
    {
    }
}

2条回答
  •  后悔当初
    2021-01-20 15:06

    Revised Answer

    Okay, so I think I've figured out why the IsGenericParameter property evaluates as false is because you were creating the MyClass type with an explicit type for .

    Since the compiler new what type the a parameter was (inferring from the instantiation of the class), I'm guessing that the compiler was treating the parameter as a non-generic type.

    Also, based upon what I was reading in MSDN, I think that the ParameterType.IsGenericParameter and Type.IsGenericType property would only evaluate to true whenever you had a method like MyMethod() vs. MyMethod(T a), where the type for is inferred from the type instantiated with the class.

    Here's a little program that demonstrates this:

    using System;
    using System.Linq;
    using System.Reflection;
    
    namespace GenericParametersViaReflectionTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                // Note: we're using the type without specifying a type for .
                var classType = typeof(MyClass<>);
    
                foreach (MethodInfo method in classType.GetMembers()
                    .Where(method => method.Name == "MyMethod"))
                {
                    // Iterate through each parameter of the method
                    foreach (var param in method.GetParameters())
                    {
                        // For generic methods, the name will be "T" and the FullName
                        // will be null; you can use which ever check you prefer.
                        if (param.ParameterType.Name == "T"
                            || param.ParameterType.FullName == null)
                            Console.WriteLine("We found our generic method!");
                        else
                            Console.WriteLine("We found the non-generic method:");
    
                        Console.WriteLine("Method Name: {0}", method.Name);
                        Console.WriteLine("Parameter Name: {0}", param.Name);
                        Console.WriteLine("Type: {0}", param.ParameterType.Name);
                        Console.WriteLine("Type Full Name: {0}",
                            param.ParameterType.FullName ?? "null");
                        Console.WriteLine("");
                    }   
                }
                Console.Read();
            }
        }
        public class MyClass
        {
            public void MyMethod(T a) { }
            public void MyMethod(int a) { }
        }
    }
    

    And the results we end up with are:

    We found or generic method!
    Method Name: MyMethod
    Parameter Name: a
    Type: T
    Type Full Name: null

    We found the non-generic method:
    Method Name: MyMethod
    Parameter Name: a
    Type: Int32
    Type Full Name: System.Int32

    If you need to create an instance of the class using a particular type, you might find the Activator.CreateInstance class useful too.


    Original Answer

    I think that if you pass in a parameter of the same datatype that matched one of the explictly set methods (e.g. the Int32 method), then the compiler would automatically select that over the one that accepts a generic parameter. Otherwise, the generic method would be selected by the compiler.

    However, if you want to be able to control which method is selected, you could modify each method to have different parameter names, while maintaining identical signatures, like so:

    public class MyClass
    {
        public void MyMethod(T genericA) {}
        public void MyMethod(int intA) {}
    }
    

    Then, using named parameters, you could explicitly call the desired method, like so:

    var foo = new MyClass();
    foo.MyMethod(genericA: 24); // This will call the "MyMethod" that only accepts .
    foo.MyMethod(intA: 19); // This will call the "MyMethod" that only accepts integers.
    

    Edit

    For some reason, in my original answer I missed the part where you mentioned using reflection, but it looks my original answer could be coupled with these other answers to give you a viable solution:

    • Invoking methods with optional parameters through reflection
    • How can you get the names of method parameters?

提交回复
热议问题