73

c#4.0の使用-インターフェイスと、インターフェイスを実装するクラスを構築します。インターフェイスでオプションのパラメータを宣言し、それをクラスに反映させたい。だから、私は次のものを持っています:

 public interface IFoo
 {
      void Bar(int i, int j=0);
 }

 public class Foo
 {
      void Bar(int i, int j=0) { // do stuff }
 }

これはコンパイルされますが、正しく見えません。インターフェイスにはオプションのパラメータが必要です。そうしないと、インターフェイスメソッドのシグネチャに正しく反映されないためです。

オプションのパラメーターをスキップして、null許容型を使用する必要がありますか?それとも、これは副作用や結果なしに意図したとおりに機能しますか?

4

6 に答える 6

65

本当に奇妙なのは、インターフェイスのオプションパラメータに設定した値が実際に違いを生むことです。値がインターフェースの詳細なのか実装の詳細なのか疑問に思う必要があると思います。私は後者を言ったでしょうが、物事は前者のように振る舞います。次のコードは、たとえば1 0 2 537を出力します。

// Output:
// 1 0
// 2 5
// 3 7
namespace ScrapCSConsole
{
    using System;

    interface IMyTest
    {
        void MyTestMethod(int notOptional, int optional = 5);
    }

    interface IMyOtherTest
    {
        void MyTestMethod(int notOptional, int optional = 7);
    }

    class MyTest : IMyTest, IMyOtherTest
    {
        public void MyTestMethod(int notOptional, int optional = 0)
        {
            Console.WriteLine(string.Format("{0} {1}", notOptional, optional));
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            MyTest myTest1 = new MyTest();
            myTest1.MyTestMethod(1);

            IMyTest myTest2 = myTest1;
            myTest2.MyTestMethod(2);

            IMyOtherTest myTest3 = myTest1;
            myTest3.MyTestMethod(3);
        }
    }
}

興味深いのは、インターフェースがパラメーターをオプションにする場合、それを実装するクラスが同じことをする必要がないことです。

// Optput:
// 2 5
namespace ScrapCSConsole
{
    using System;

    interface IMyTest
    {
        void MyTestMethod(int notOptional, int optional = 5);
    }

    class MyTest : IMyTest
    {
        public void MyTestMethod(int notOptional, int optional)
        {
            Console.WriteLine(string.Format("{0} {1}", notOptional, optional));
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            MyTest myTest1 = new MyTest();
            // The following line won't compile as it does not pass a required
            // parameter.
            //myTest1.MyTestMethod(1);

            IMyTest myTest2 = myTest1;
            myTest2.MyTestMethod(2);
        }
    }
}

ただし、間違いのように思われるのは、インターフェイスを明示的に実装した場合、オプションの値のクラスで指定した値は無意味であるということです。次の例では、値9をどのように使用できますか?

// Optput:
// 2 5
namespace ScrapCSConsole
{
    using System;

    interface IMyTest
    {
        void MyTestMethod(int notOptional, int optional = 5);
    }

    class MyTest : IMyTest
    {
        void IMyTest.MyTestMethod(int notOptional, int optional = 9)
        {
            Console.WriteLine(string.Format("{0} {1}", notOptional, optional));
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            MyTest myTest1 = new MyTest();
            // The following line won't compile as MyTest method is not available
            // without first casting to IMyTest
            //myTest1.MyTestMethod(1);

            IMyTest myTest2 = new MyTest();            
            myTest2.MyTestMethod(2);
        }
    }
}

Eric Lippertは、この正確なトピックについて興味深いシリーズを書きました。オプションの引数コーナーケース

于 2013-12-19T15:53:00.007 に答える
30

pre-optional-parametersの代替案を検討できます。

public interface IFoo
{
    void Bar(int i, int j);
}

public static class FooOptionalExtensions
{
    public static void Bar(this IFoo foo, int i)
    {
        foo.Bar(i, 0);
    }
}

新しい言語機能の外観が気に入らない場合は、それを使用する必要はありません。

于 2010-04-02T14:39:09.113 に答える
4

実装でパラメータをオプションにする必要はありません。あなたのコードはそれよりいくらか意味があります:

 public interface IFoo
 {
      void Bar(int i, int j = 0);
 }

 public class Foo
 {
      void Bar(int i, int j) { // do stuff }
 }

このように、デフォルト値が何であるかは明確です。実際、インターフェイスがデフォルト値を提供するため、実装のデフォルト値は効果がないと確信しています。

于 2014-07-31T13:26:35.993 に答える
3

このようなものはどうですか?

public interface IFoo
{
    void Bar(int i, int j);
}

public static class IFooExtensions 
{
    public static void Baz(this IFoo foo, int i, int j = 0) 
    {
        foo.Bar(i, j);
    }
}

public class Foo
{
    void Bar(int i, int j) { /* do stuff */ }
}
于 2012-04-19T13:44:20.907 に答える
2

考慮すべきことは、インターフェースの反映に基づいて機能するモックフレームワークが使用されたときに何が起こるかです。オプションのパラメータがインターフェイスで定義されている場合、デフォルト値はインターフェイスで宣言されている内容に基づいて渡されます。1つの問題は、定義にさまざまなオプション値を設定することを妨げるものが何もないということです。

于 2014-11-14T15:05:06.373 に答える
0

私もこれを提案することができます:

public interface IFoo
{
      void Bar(int i);
      void Bar(int i, int j);
}

public class Foo
{
     // when "j" has default value zero (0).
     void Bar(int i)
     {
         Bar(i, 0);
     }
     
     void Bar(int i, int j) {}
}
于 2021-08-02T16:03:37.610 に答える