1

タイプAのパラメーターをパラメーターとして期待している代理人がいます。したがって、Aは基本クラスです。クラスBとCはAから継承します。

問題は、BとCが基本クラスAから継承しているにもかかわらず、スクリプトの下部にあるDoSomething関数をデリゲートに変換できないことです。

public class A { }
public class B : A { }
public class C : A { }

public delegate void CallbackAction(params A[] paremeters);
public class Main
{
    public int main(params string[] args)
    {
        CallbackAction callbackAction;
        callbackAction = DoSomething1;
        callbackAction = DoSomething2;
        callbackAction = DoSomething3;

        return 0;
    }

    public void DoSomething1(A arg0) { }
    public void DoSomething2(B arg0) { }
    public void DoSomething3(C arg0) { }
}

デリゲートでparamsを使用し、paramsクラスを基本クラスとして持つクラスを使用できるようにする方法はありますか?

エラーをコンパイルすると、次のようになります。エラー5「DoSomething3」のオーバーロードはデリゲート「SKConsole.CallbackAction」と一致しません

.NET4とXNAを使用しています

編集:: わかりました、なぜ私がこれを使用しているのか説明させてください私はコンソールを作成しています。これは、私のコンソールを使用しているプログラマーがコマンド(console.AddCommand( "help"、Help))をコンソールに追加できることを意味します。ここでのヘルプは関数です。ゲーム内でコンソールにヘルプを入力すると、関数Help()が実行されます。 。これで、console.AddCommand( "setSpeed"、SetPlayerSpeed)でも機能するようにします。SetPlayerSpeed関数には1つのパラメーター、intがあります。ただし、任意の関数で機能するようにしたいので、プログラマーが関数DoSomeFancyStuff(float a 、string b、int c)コンソールでコマンドを作成し、コンソールに正しい文字列を入力した場合は、これらのコマンドを実行します。

私はすでにさまざまな機能のためにたくさんのデリゲートを作成しようとしましたが、これは私の意見ではちょっと醜いです。

それから私が試したのは次のことでした

public abstract class SKConsoleParameter
{
    protected string value;

    public SKConsoleParameter(string value)
    {
        this.value = value;
    }
    public string GetRawValue()
    {
        return value;
    }

    public abstract bool IsValid();
    public abstract object GetValue();
}

public class StringParam : SKConsoleParameter
{
    public StringParam(string value) : base(value) { }

    public override bool IsValid()
    {
        return true;
    }

    public override object GetValue()
    {
        return value;
    }
}

public class IntParam : SKConsoleParameter
{
    public IntParam(string value) : base(value) { }

    public override bool IsValid()
    {
        int i;
        return int.TryParse(value, out i);
    }

    public override object GetValue()
    {
        int i;
        if (int.TryParse(value, out i))
            return i;
        else
            return 0;
    }
}

これは、開発者が次のような関数を作成した場合です。

DoSomethingCool(StringParam s, IntParam i)

次に、(string)s.GetValue()と(int)i.GetValue()を使用して値を受け取ることができます。StringParamクラスとIntParamクラスはどちらもSKConsoleParameterを継承しているため、次のデリゲートを作成できます。

void CoolDelegate(params SKConsoleParameter[] parameters)

しかし、これは機能しません。このページの上部にあるクラスA、B、およびCの抽象的な問題のため。

誰かがこの問題に対抗するためのアイデアを持っていますか?

4

3 に答える 3

1

間違った場所でエラーを探しています。C#では、デリゲートの入力パラメーターの反変性が許可されます。params A[]コードの問題は、メソッドが単一のをとるのに対し、デリゲートはをとるということAです。これは許可されていません。シングルを受け入れるようにあなたの代理人をデルケアしますA

delegate void Callback1 (B a) ;
void Test11 (A a) {}
void Test12 (B b) {}

Callback1 c11 = Test11 ; // OK
Callback1 c12 = Test12 ; // OK

これは配列パラメータでは機能しないことにも注意してください。

delegate void Callback2 (B[] a) ;
void Test21 (A[] a) {}
void Test22 (B[] b) {}

Callback2 c21 = Test21 ; // compile error
Callback2 c22 = Test22 ; // OK
于 2013-02-27T14:19:58.237 に答える
0

このコードを試してください:

 public class A {  }
public class B : A { }
public class C : A { }

public static class Helper
{
    public static Action<A> DoSomething;
}

class Program
{
    static void Main(string[] args)
    {
        var a = new A();
        var b = new B();
        var c = new C();

        Helper.DoSomething = new Action<A>(DoSomething1);
        Helper.DoSomething = (Action<A>)new Action<B>(DoSomething2);
        Helper.DoSomething = (Action<A>)new Action<C>(DoSomething3);                       
    }

    public static void DoSomething1(A a) { }
    public static void DoSomething2(B a) { }
    public static void DoSomething3(C a) { }
}
于 2013-02-27T14:18:53.690 に答える
0

更新されたコードに基づいて-これを試してください。メソッドがデリゲートと一致する限り、.NET3.5以降で期待どおりに反変性が機能するはずです。

public abstract class SKConsoleParameter
{
    protected string value;

    public SKConsoleParameter(string value)
    {
        this.value = value;
    }
    public string GetRawValue()
    {
        return value;
    }

    public abstract bool IsValid();
    public abstract object GetValue();
}

public class StringParam : SKConsoleParameter
{
    public StringParam(string value) : base(value) { }

    public override bool IsValid()
    {
        return true;
    }

    public override object GetValue()
    {
        return value;
    }
}

public class IntParam : SKConsoleParameter
{
    public IntParam(string value) : base(value) { }
    public override bool IsValid()
    {
        int i;
        return int.TryParse(value, out i);
    }
    public override object GetValue()
    {
        int i;
        if (int.TryParse(value, out i))
            return i;
        else
            return 0;
    }
}   

class Program
{

    public delegate void CoolDelegate(params SKConsoleParameter[] parameters);

    static void Main(string[] args)
    {
        var s = new StringParam("Glenn");
        var i = new IntParam("12");
        var coolDel = new CoolDelegate(DoSomethingCool);
        coolDel(s, i);
    }

    public static void DoSomethingCool(params SKConsoleParameter[] parameters)
    {
        if (parameters == null) throw new ArgumentNullException("parameters");
        foreach (var item in parameters)
        {
            if (item is IntParam)
            {
                // do something interesting
                continue;
            }

            if (item is StringParam)
            {
                // do something else interesting
                continue;
            }

            throw new NotImplementedException("unknown param type");
        }
    }
}
于 2013-02-27T19:54:12.883 に答える