polimorfico - ¿ en c# qué es el polimorfismo?
¿Por qué usar un método público en una clase interna? (10)
Hay muchos códigos en uno de nuestros proyectos que se parecen a esto:
internal static class Extensions
{
public static string AddFoo(this string s)
{
if (!string.IsNullOrEmpty(s)) return s + "Foo";
return "Foo";
}
}
¿Hay alguna razón explícita para hacer esto que no sea "es más fácil hacer el tipo público más adelante?"
Sospecho que solo importa en casos muy extraños (reflejo en Silverlight) o en absoluto.
A menudo, marco mis métodos en clases internas como públicas, en lugar de internas, ya que a) realmente no importa yb) uso interno para indicar que el método es interno a propósito (hay alguna razón por la que no quiero exponer esto método en una clase pública. Por lo tanto, si tengo un método interno, realmente tengo que entender la razón por la que es interno antes de cambiarlo a público, mientras que si estoy tratando con un método público en una clase interna, realmente tengo que pensar por qué la clase es interna en oposición a por qué cada método es interno.
ACTUALIZACIÓN: Esta pregunta fue el tema de mi blog en septiembre de 2014 . Gracias por la gran pregunta!
Existe un debate considerable sobre esta cuestión incluso dentro del propio equipo del compilador.
En primer lugar, es sabio entender las reglas. Un miembro público de una clase o estructura es un miembro al que puede acceder cualquier cosa que pueda acceder al tipo que lo contiene . Entonces, un miembro público de una clase interna es efectivamente interno.
Entonces, dada una clase interna, ¿deberían sus miembros a los que desea acceder en la asamblea ser marcados como públicos o internos?
Mi opinión es: marcar tales miembros como público.
Uso "público" para decir "este miembro no es un detalle de implementación". Un miembro protegido es un detalle de implementación; Hay algo al respecto que se necesitará para que una clase derivada funcione. Un miembro interno es un detalle de implementación; algo más interno a este ensamblaje necesita el miembro para funcionar correctamente. Un miembro público dice "este miembro representa la clave, la funcionalidad documentada proporcionada por este objeto".
Básicamente, mi actitud es: supongo que decidí convertir esta clase interna en una clase pública. Para hacer eso, quiero cambiar exactamente una cosa : la accesibilidad de la clase. Si convertir una clase interna en una clase pública significa que también tengo que convertir a un miembro interno en un miembro público, ese miembro era parte del área pública de la clase y, en primer lugar, debería haber sido pública.
Otras personas no están de acuerdo. Hay un contingente que dice que quieren poder echar un vistazo a la declaración de un miembro y saber de inmediato si se va a llamar solo desde el código interno.
Desafortunadamente, eso no siempre funciona bien; por ejemplo, una clase interna que implementa una interfaz interna aún debe tener los miembros de la implementación marcados como públicos, porque son parte de la superficie pública de la clase .
Creo que tengo una opinión adicional sobre esto. Al principio, me preguntaba cómo tiene sentido declarar algo al público en una clase interna. Luego terminé aquí, leyendo que podría ser bueno si luego decides cambiar la clase a público. Cierto. Entonces, se formó un patrón en mi mente: si no cambia el comportamiento actual, entonces sea permisivo y permita cosas que no tienen sentido (y no duelen) en el estado actual del código, pero luego lo haría, si Cambiar la declaración de la clase.
Me gusta esto:
public sealed class MyCurrentlySealedClass
{
protected void MyCurretlyPrivateMethod()
{
}
}
De acuerdo con el "patrón" que he mencionado anteriormente, esto debería estar perfectamente bien. Sigue la misma idea. Se comporta como un método private
, ya que no se puede heredar la clase. Pero si elimina la restricción sealed
, sigue siendo válida: las clases heredadas pueden ver este método, que es absolutamente lo que quería lograr. Pero CS0628
una advertencia: CS0628
o CA1047
. Ambos están a punto de no declarar miembros protected
en una clase sealed
. Por otra parte, he encontrado un acuerdo total sobre el hecho de que no tiene sentido: advertencia de ''Miembro protegido en clase sellada'' (una clase singleton)
Entonces, después de esta advertencia y la discusión vinculada, he decidido hacer que todo sea interno o menos, en una clase interna, porque se ajusta más a ese tipo de pensamiento, y no mezclamos diferentes "patrones".
En algunos casos, también puede ser que el tipo interno implemente una interfaz pública, lo que significaría que cualquier método definido en esa interfaz aún debería declararse como público.
Es el mismo, el método público se marcará realmente como interno ya que está dentro de una clase interna, pero tiene una ventaja (como ha invitado), si desea marcar la clase como pública, tiene que cambiar menos código.
Hay una diferencia. En nuestro proyecto hemos realizado muchas clases internas, pero realizamos pruebas de unidad en otro conjunto y en nuestra información de conjunto utilizamos InternalsVisibleTo para permitir que el conjunto UnitTest llame a las clases internas. He notado que si la clase interna tiene un constructor interno, no podemos crear una instancia usando Activator.CreateInstance en el ensamblaje de prueba de unidad por alguna razón. Pero si cambiamos el constructor a público pero la clase sigue siendo interna, funciona bien. Pero supongo que este es un caso muy raro (como dijo Eric en la publicación original: Reflexión).
Realmente luché con esto hoy. Hasta ahora, habría dicho que todos los métodos deberían estar marcados con internal
si la clase fuera internal
y hubiera considerado cualquier otra cosa simplemente mala codificación o pereza, especialmente en el desarrollo empresarial; sin embargo, tuve que subclasificar una clase public
y anular uno de sus métodos:
internal class SslStreamEx : System.Net.Security.SslStream
{
public override void Close()
{
try
{
// Send close_notify manually
}
finally
{
base.Close();
}
}
}
El método DEBE ser public
y me hizo pensar que realmente no hay un punto lógico para establecer métodos como internal
menos que realmente deban serlo, como dijo Eric Lippert.
Hasta ahora nunca me he parado a pensar en ello, simplemente lo acepté, pero después de leer el post de Eric realmente me hizo pensar y después de mucho deliberar tiene mucho sentido.
Si la clase es internal
, no importa desde el punto de vista de la accesibilidad si marca un método internal
o public
. Sin embargo, todavía es bueno usar el tipo que usarías si la clase fuera public
.
Si bien algunos han dicho que esto facilita las transiciones de lo internal
a lo public
. También sirve como parte de la descripción del método. Internal
métodos Internal
generalmente se consideran inseguros para el acceso sin restricciones, mientras que public
métodos public
se consideran juegos (en su mayoría) gratuitos.
Al utilizar internal
o public
como lo haría en una clase public
, se asegura de que está comunicando qué estilo de acceso se espera, al tiempo que facilita el trabajo necesario para hacer que la clase sea public
en el futuro.
Sospecho que "es más fácil hacer público el tipo más tarde?" Lo es.
Las reglas de alcance significan que el método solo será visible como internal
, por lo que realmente no importa si los métodos están marcados como public
o internal
.
Una posibilidad que se me ocurre es que la clase era pública y luego se cambió a internal
y el desarrollador no se molestó en cambiar todos los modificadores de accesibilidad del método.
internal
dice que solo se puede acceder al miembro desde el mismo ensamblaje. Otras clases en ese conjunto pueden acceder al miembro internal public
, pero no podrían acceder a un miembro private
o protected
, internal
o no.