Pregunta

Estoy buscando el equivalente en C# de Java final.¿Existe?

Hace C# tienen nada parecido a lo siguiente:

public Foo(final int bar);

En el ejemplo anterior, bar es una variable de sólo lectura y no puede ser cambiado por Foo().Hay alguna forma de hacer esto en C#?

Por ejemplo, tal vez tengo una larga método que se va a trabajar con x, y, y z las coordenadas de un objeto (ints).Quiero estar absolutamente seguro de que la función no alterar estos valores en cualquier forma, con lo que la corrupción de los datos.Por lo tanto, me gustaría declarar readonly.

public Foo(int x, int y, int z) {
     // do stuff
     x++; // oops. This corrupts the data. Can this be caught at compile time?
     // do more stuff, assuming x is still the original value.
}
¿Fue útil?

Solución

Por desgracia no se puede hacer esto en C #.

El const palabra clave sólo puede ser utilizado para las variables y campos locales.

El readonly palabra clave sólo puede ser utilizado en campos.

  

NOTA: El lenguaje Java también es compatible con los parámetros finales a un método. Esta funcionalidad es inexistente en C #.

desde http://www.25hoursaday.com/CsharpVsJava.html

EDIT (08.13.2019): Estoy lanzando esta en la visibilidad ya que este es aceptado y el más alto en la lista. Ahora es posible con la clase de parámetros in. Ver la respuesta debajo de éste para obtener más información.

Otros consejos

Esto es ahora posible en C # versión 7.2:

Se puede utilizar la palabra clave in en la firma del método. MSDN la documentación .

La palabra clave in debe añadirse antes de especificar el argumento de un método.

ejemplo, un método válido en C # 7.2:

public long Add(in long x, in long y)
{
    return x + y;
}

Si bien no se permite lo siguiente:

public long Add(in long x, in long y)
{
    x = 10; // It is not allowed to modify an in-argument.
    return x + y;
}

se mostrará el error siguiente al intentar modificar cualquiera x o y ya que están marcados con in:

  

No se puede asignar a la variable 'largo' porque es una variable de sólo lectura

Marcado una discusión con medios in:

  

Este método no modifica el valor del argumento utilizado como este parámetro.

Voy a empezar con la parte int. int es un tipo de valor, y en Net que significa que realmente se trata de una copia. Es una restricción de diseño muy raro que contar un método "Usted puede tener una copia de este valor es su copia, no el mío;. Nunca voy a ver de nuevo, pero no se puede cambiar la copia.". Es implícito en la llamada al método que copiar este valor está bien, de lo contrario no podríamos haber llamado con seguridad el método. Si el método necesita el original, dejar que el implementador para hacer una copia para guardarla. O bien dar al método del valor o no se dé por el método del valor. No ir todo endeble en el medio.

mover Vamos a los tipos de referencia. Ahora se pone un poco confuso. ¿Se refiere a una referencia constante, donde la referencia en sí no puede ser cambiado, o un objeto inmutable completamente cerrada? En el primer caso, las referencias en .Net por defecto se pasan por valor. Es decir, se obtiene una copia de la referencia. Así que tenemos esencialmente la misma situación que para los tipos de valor. Si el implementador tendrá la referencia original se puede mantener por sí mismos.

Esto nos deja sólo con constante (Bloqueado / inmutable) objeto. Esto puede parecer bien, desde una perspectiva de tiempo de ejecución, pero ¿cómo es el compilador de hacerla cumplir? Dado que las propiedades y métodos, todos ellos pueden tener efectos secundarios, que esencialmente estaría limitado a acceso de sólo lectura de campo. Este tipo de objeto no es probable que sea muy interesante.

La respuesta:. C # no tiene la funcionalidad const como C ++

Estoy de acuerdo con Bennett eneldo.

La palabra clave const es muy útil. En el ejemplo, que utilizó un int y la gente no recibe su punto. Pero, ¿por qué si el parámetro es un enorme y complejo objeto de usuario que no se puede cambiar dentro de esa función? Ese es el uso de la palabra clave const: parámetro no se puede cambiar dentro de ese método porque [la razón que sea aquí] que no lo hace importante para ese método. palabra clave const es muy potente y realmente se pierda en C #.

Aquí hay un corto y dulce respuesta que probablemente obtener una gran cantidad de votos hacia abajo. No he leído todos los mensajes y comentarios, así que por favor me perdone si esto se ha sugerido anteriormente.

¿Por qué no toma sus parámetros y los pasa en un objeto que los expone como inmutable y luego usar ese objeto en su método?

Me di cuenta que es probablemente un trabajo muy evidente en torno a que ya se ha considerado y el PO está tratando de evitar hacer esto con esta pregunta, pero sentí que debería estar aquí ninguno de los de menos ...

Buena suerte: -)

Crear una interfaz para la clase que sólo tiene propiedad readonly descriptores de acceso.A continuación, tendrá su parámetro de la interfaz en lugar de la propia clase.Ejemplo:

public interface IExample
{
    int ReadonlyValue { get; }
}

public class Example : IExample
{
    public int Value { get; set; }
    public int ReadonlyValue { get { return this.Value; } }
}


public void Foo(IExample example)
{
    // Now only has access to the get accessors for the properties
}

Para estructuras, crear un genérico const contenedor.

public struct Const<T>
{
    public T Value { get; private set; }

    public Const(T value)
    {
        this.Value = value;
    }
}

public Foo(Const<float> X, Const<float> Y, Const<float> Z)
{
// Can only read these values
}

Cabe destacar sin embargo, que la extrañeza de la que desea hacer lo que le estás pidiendo que haga con respecto a las estructuras, como el escritor de el método que usted debe esperar para saber que pasa en ese método.No afectará a los valores pasados a modificar dentro del método, así que su única preocupación es asegurarse de que usted se comportan de sí mismo en el método que está escrito.Llega un punto donde la vigilancia y el código limpio son la clave, sobre cumplimiento de const y otras reglas.

Si a menudo se meten en problemas como éste, entonces debería considerar "aplicaciones húngaro". El buen tipo, a diferencia de la mala clase . Si bien esto normalmente no intenta expresar constante-dad de un parámetro del método (que es demasiado inusual), ciertamente no hay nada que le para de viradas un extra "c" antes del nombre de identificador.

Para todos aquellos dolor para cerrar de golpe el botón downvote ahora, por favor leer las opiniones de estas luminarias sobre el tema:

Sé que esto puede ser poco tarde. Pero para las personas que todavía están buscando otras maneras para esto, podría haber otra forma de evitar esto limitación de C # estándar. Podríamos escribir contenedor de clase de sólo lectura donde T: struct. Con la conversión implícita de tipo base T. Pero la conversión sólo se expresa a envoltorio clase. ¿Qué hará cumplir los errores del compilador si intenta desarrollador conjunto implícita al valor de sólo lectura Tipo. Como demostraré dos posibles usos a continuación.

USO 1 requiere que llama definición al cambio. Este uso tendrá que utilizar sólo en las pruebas para la corrección de su código de funciones "TestCalled". Mientras que en el nivel de la salida / construyo usted no debe usarlo. Dado que en gran escala operaciones matemáticas podrían exageración en las conversiones, y hacer que el código lento. Yo no lo uso, pero para fines de demostración solamente he fijado a él.

USO 2, que yo sugeriría, tiene depuración vs uso de lanzamiento demostrado en función TestCalled2. También habría ninguna conversión en función TestCaller cuando se utiliza este enfoque, pero requiere un poco más de la codificación de las definiciones TestCaller2 usando el compilador acondicionado. Se puede notar errores de compilación en configuración de depuración, mientras que en la configuración de liberación todo el código de la función TestCalled2 compilará correctamente.

using System;
using System.Collections.Generic;

public class ReadOnly<VT>
  where VT : struct
{
  private VT value;
  public ReadOnly(VT value)
  {
    this.value = value;
  }
  public static implicit operator VT(ReadOnly<VT> rvalue)
  {
    return rvalue.value;
  }
  public static explicit operator ReadOnly<VT>(VT rvalue)
  {
    return new ReadOnly<VT>(rvalue);
  }
}

public static class TestFunctionArguments
{
  static void TestCall()
  {
    long a = 0;

    // CALL USAGE 1.
    // explicite cast must exist in call to this function
    // and clearly states it will be readonly inside TestCalled function.
    TestCalled(a);                  // invalid call, we must explicit cast to ReadOnly<T>
    TestCalled((ReadOnly<long>)a);  // explicit cast to ReadOnly<T>

    // CALL USAGE 2.
    // Debug vs Release call has no difference - no compiler errors
    TestCalled2(a);

  }

  // ARG USAGE 1.
  static void TestCalled(ReadOnly<long> a)
  {
    // invalid operations, compiler errors
    a = 10L;
    a += 2L;
    a -= 2L;
    a *= 2L;
    a /= 2L;
    a++;
    a--;
    // valid operations
    long l;
    l = a + 2;
    l = a - 2;
    l = a * 2;
    l = a / 2;
    l = a ^ 2;
    l = a | 2;
    l = a & 2;
    l = a << 2;
    l = a >> 2;
    l = ~a;
  }


  // ARG USAGE 2.
#if DEBUG
  static void TestCalled2(long a2_writable)
  {
    ReadOnly<long> a = new ReadOnly<long>(a2_writable);
#else
  static void TestCalled2(long a)
  {
#endif
    // invalid operations
    // compiler will have errors in debug configuration
    // compiler will compile in release
    a = 10L;
    a += 2L;
    a -= 2L;
    a *= 2L;
    a /= 2L;
    a++;
    a--;
    // valid operations
    // compiler will compile in both, debug and release configurations
    long l;
    l = a + 2;
    l = a - 2;
    l = a * 2;
    l = a / 2;
    l = a ^ 2;
    l = a | 2;
    l = a & 2;
    l = a << 2;
    l = a >> 2;
    l = ~a;
  }

}

Si estructura se pasa a un método, a menos que sea aprobada por ref, no va a ser cambiado por el método se pasó a. Así que en ese sentido, sí.

Se puede crear un parámetro cuyo valor no puede ser asignado dentro del método o cuyas propiedades no se puede ajustar mientras que en el método? No. No puede evitar que el valor de ser asignado dentro del método, pero se puede evitar que sus propiedades de ser fijado por la creación de un tipo inmutable.

La cuestión no es si el parámetro o sus propiedades se pueden asignar a dentro del método. La pregunta es ¿qué será cuando las salidas de método.

La única vez que los datos fuera va a ser alterada es si pasa una clase de cambio y una de sus propiedades, o si se pasa un valor usando la palabra clave ref. La situación se ha contorneado hace ninguno.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top