Подтвердить что ты не робот

Незначительная ошибка вызова конструктора

У меня есть класс под названием Test, который имеет constructor для принятия Action<T>, а другой принимает Func<T,T>. См. Ниже фрагмент.

public class Test<T>
{
    //constructors
    public Test() { }
    public Test(Action<T> action) { }
    public Test(Func<T, T> action) { }

    //methods with same signature of constructor
    public void MyMethod1(Action<T> action) { }
    public void MyMethod2(Func<T, T> action) { }
}


public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        Test<string> t1 = new Test<string>(this.MyMethod1);
        Test<string> t2 = new Test<string>(this.MyMethod2);

        Test<string> t = new Test<string>();
        t.MyMethod1(MyMethod1);
        t.MyMethod2(MyMethod2);
    }

    public void MyMethod1(string value) { }
    public string MyMethod2(string value) { return string.Empty; }

}

Но ниже строк вызывается неоднозначная ошибка вызова

Test<string> t1 = new Test<string>(this.MyMethod1);
Test<string> t2 = new Test<string>(this.MyMethod2);

и интересным моментом является то, что у меня есть два метода с одной и той же сигнатурой моего класса Test constructor, который не бросает какую-либо неоднозначную ошибку

Test<string> t = new Test<string>();
t.MyMethod1(MyMethod1);
t.MyMethod2(MyMethod2);

Может ли кто-нибудь помочь мне определить и исправить проблему.

4b9b3361

Ответ 1

Возвращаемое значение метода не является частью его подписи. Учитываются только параметры. Следовательно, компилятор не может различать Action<T> и Func<T,T>. Подробное объяснение и обходные пути можно найти fooobar.com/questions/378929/...

Ответ 2

Вы можете попробовать переименовать параметры для каждого из ваших конструкторов следующим образом:

public class Test<T>
{
    public Test() { }
    public Test(Action<T> action) { }
    public Test(Func<T,T> function) { }
}

Поэтому, когда вы создаете экземпляр класса, вы можете указать имя параметра следующим образом:

var objectWithAction = new Test<string>(action: Method1);
var objectWithFunction = new Test<string>(function: Method2);

Ответ 3

Факт

метод/перегрузка конструктора может распознать правильный метод по типам параметров, но не включает тип возвращаемого значения.

Причина

И поскольку в обоих упомянутых конструкторах в вопросе параметр имеет тип MethodGroup, поэтому компилятор не может определить правильную перегрузку. во-вторых, вызовы метода успешны, так как это не сценарий перегрузки.

Разрешение

вот возможные варианты решения проблемы

завершение вызова метода в анонимный вызов метода и возможность неявного преобразования различать себя.

    Test<string> t1 = new Test<string>(s => this.MyMethod1(s));
    Test<string> t2 = new Test<string>(s => { return this.MyMethod2(s); });

результат

result


Альтернативный подход

другой вариант состоит в том, чтобы явно ввести группу методов

    Test<string> t1 = new Test<string>((Action<string>)this.MyMethod1);
    Test<string> t2 = new Test<string>((Func<string, string>)this.MyMethod2);

это бит дольше, чем первый подход, если параметры меньше

Ответ 4

здесь пример рабочего приложения консоли

class Program
    {
        static void Main(string[] args)
        {
            Test<string> t1 = new Test<string>(action: MyMethod1);
            Test<string> t2 = new Test<string>(function: MyMethod2);


            Test<string> t = new Test<string>();
            t.MyMethod1(MyMethod1);
            t.MyMethod2(MyMethod2);
        }
        public static void MyMethod1(string value)
        {
            Console.WriteLine("my method1 {0}", value);
        }
        public static string MyMethod2(string value)
        {
            Console.WriteLine("my method2 {0}", value);
            return string.Empty;
        }
    }
    public class Test<T>
    {
        //constructors
        public Test() { }
        public Test(Action<T> action)
        {

            object args = "action";
            action.Invoke((T)args); // here you should invoke the method in order to execute it
        }
        public Test(Func<T, T> function)
        {
            object args = "function";
            function.Invoke((T)args);
        }

        //methods with same signature of constructor
        public void MyMethod1(Action<T> action)
        {
            object args = "Method 3";
            action.Invoke((T)args);
        }
        public void MyMethod2(Func<T, T> action)
        {
            object args = "Method 4";
            action.Invoke((T)args);
        }
    }

надеюсь, что это поможет вам

приветствует