Parámetros opcionales para interfaces


Usando c# 4.0 building construyendo una interfaz y una clase que implemente la interfaz. Quiero declarar un parámetro opcional en la interfaz y que se refleje en la clase. Por lo tanto, tengo lo siguiente:

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

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

Esto compila, pero no se ve bien. La interfaz necesita tener los parámetros opcionales, porque de lo contrario no se refleja correctamente en la firma del método de interfaz.

¿Debo omitir el parámetro opcional y simplemente usar un tipo nullable? O será esto trabajar según lo previsto sin efectos secundarios o consecuencias?

Author: Ahmad Mageed, 2010-04-02

6 answers

Podría considerar la alternativa de parámetros pre-opcionales:

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);
    }
}

Si no te gusta el aspecto de una nueva función de idioma, no tienes que usarla.

 28
Author: pdr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-02 14:39:09

Lo que es realmente extraño es que el valor que pone para el parámetro opcional en la interfaz realmente hace una diferencia. Supongo que tienes que preguntar si el valor es un detalle de interfaz o un detalle de implementación. Habría dicho lo último, pero las cosas se comportan como las primeras. El siguiente código produce 1 0 2 5 3 7 por ejemplo.

// 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);
        }
    }
}

Lo que es interesante es que si su interfaz hace que un parámetro opcional de la clase de aplicación que no tiene que hacer el mismo:

// 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);
        }
    }
}

Lo que parece ser un error sin embargo es que si implementa la interfaz explícitamente el valor que da en la clase para el valor opcional no tiene sentido. ¿Cómo en el siguiente ejemplo podría utilizar el valor 9? Esto ni siquiera da una advertencia al compilar.

// 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);
        }
    }
}
 50
Author: Martin Brown,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-02 12:53:50

¿Qué hay de algo como esto?

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 */ }
}
 3
Author: Dave,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-26 17:55:29

No tiene que hacer que el parámetro sea opcional en la implementación. Su código tendrá un poco más de sentido entonces:

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

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

De esta manera, es inequívoco cuál es el valor predeterminado. De hecho, estoy bastante seguro de que el valor predeterminado en la implementación no tendrá ningún efecto, ya que la interfaz proporciona un valor predeterminado para ella.

 3
Author: Tor Haugen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-31 13:26:35

Lo que hay que tener en cuenta es lo que sucede cuando se utilizan frameworks de burla, que funcionan basados en la reflexión de la interfaz. Si se definen parámetros opcionales en la interfaz, el valor predeterminado se pasará en función de lo declarado en la interfaz. Un problema es que no hay nada que le impida establecer diferentes valores opcionales en la definición.

 2
Author: Hitesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-02 17:56:21

Mira a un lado, eso hará exactamente lo que parece que quieres lograr.

 1
Author: MojoFilter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-06 18:06:11