Respuestas:
El mayor uso de las clases parciales es facilitar la vida de los generadores / diseñadores de código. Las clases parciales permiten al generador simplemente emitir el código que necesitan emitir y no tienen que ocuparse de las ediciones del usuario en el archivo. Los usuarios también son libres de anotar la clase con nuevos miembros al tener una segunda clase parcial. Esto proporciona un marco muy limpio para la separación de preocupaciones.
Una mejor manera de verlo es ver cómo funcionaban los diseñadores antes de las clases parciales. El diseñador de WinForms escupiría todo el código dentro de una región con comentarios fuertemente redactados sobre no modificar el código. Tuvo que insertar todo tipo de heurísticas para encontrar el código generado para su posterior procesamiento. Ahora puede simplemente abrir el archivo designer.cs y tener un alto grado de confianza de que solo contiene código relevante para el diseñador.
Otro uso es dividir la implementación de diferentes interfaces, por ejemplo:
partial class MyClass : IF1, IF2, IF3
{
// main implementation of MyClass
}
partial class MyClass
{
// implementation of IF1
}
partial class MyClass
{
// implementation of IF2
}
Implements
palabra clave para indicar que un método pertenece a una interfaz)
Aparte de las otras respuestas ...
Los he encontrado útiles como un trampolín en la refactorización de las clases de dioses. Si una clase tiene múltiples responsabilidades (especialmente si es un archivo de código muy grande), entonces considero beneficioso agregar 1x clase parcial por responsabilidad como primer paso para organizar y luego refactorizar el código.
Esto ayuda enormemente porque puede ayudar a hacer que el código sea mucho más legible sin afectar realmente el comportamiento de ejecución. También puede ayudar a identificar cuándo una responsabilidad es fácil de refactorizar o está estrechamente enredada con otros aspectos.
Sin embargo, para ser claros, este sigue siendo un código incorrecto, al final del desarrollo aún desea una responsabilidad por clase ( NO por clase parcial). Es solo un trampolín :)
Declaración parcial del método solamente Incluso el código se compila solo con la declaración del método y si la implementación del método no está presente, el compilador puede eliminar ese fragmento de código de forma segura y no se producirá ningún error en el tiempo de compilación.
Para verificar el punto 4. Simplemente cree un proyecto winform e incluya esta línea después del Form1 Constructor e intente compilar el código
partial void Ontest(string s);
Aquí hay algunos puntos a considerar al implementar clases parciales: -
Un gran uso es separar el código generado del código escrito a mano que pertenece a la misma clase.
Por ejemplo, dado que LINQ to SQL usa clases parciales, puede escribir su propia implementación de ciertas funciones (como las relaciones de Muchos a Muchos) y esas piezas de código personalizado no se sobrescribirán cuando vuelva a generar el código.
Lo mismo ocurre con el código WinForms. Todo el código generado por el diseñador va en un archivo que generalmente no toca. Su código escrito a mano va en otro archivo. De esa manera, cuando cambias algo en Designer, tus cambios no quedan impresionados.
Es cierto que Partial Class se usa en la generación automática de código, un uso puede ser mantener un archivo de clase grande que podría tener miles de líneas de código. Nunca se sabe que su clase podría terminar con 10 mil líneas y no desea crear una nueva clase con un nombre diferente.
public partial class Product
{
// 50 business logic embedded in methods and properties..
}
public partial class Product
{
// another 50 business logic embedded in methods and properties..
}
//finally compile with product.class file.
Otro posible uso podría ser que más de un desarrollador pueda trabajar en la misma clase, ya que están almacenados en diferentes lugares. La gente puede reírse, pero nunca se sabe que a veces puede ser difícil.
public partial class Product
{
//you are writing the business logic for fast moving product
}
public partial class Product
{
// Another developer writing some business logic...
}
Espero que tenga sentido!
Las clases parciales abarcan múltiples archivos.
¿Cómo puede usar el modificador parcial en una declaración de clase C #?
Con clases parciales, puede separar físicamente una clase en varios archivos. Esto a menudo lo hacen los generadores de código.
Ejemplo
Con las clases normales de C #, no puede declarar una clase en dos archivos separados en el mismo proyecto. Pero con el partial
modificador, puedes.
Esto es útil si un archivo se edita comúnmente y el otro es generado por máquina o rara vez editado.
Aquí hay un ejemplo para aclarar:
class Program
{
static void Main()
{
A.A1();
A.A2();
}
}
Contenido del archivo A1.cs: C #
using System;
partial class A
{
public static void A1()
{
Console.WriteLine("A1");
}
}
Contenido del archivo A2.cs: C #
using System;
partial class A
{
public static void A2()
{
Console.WriteLine("A2");
}
}
Salida:
A1
A2
Parcial se requiere aquí.
Si elimina el partial
modificador, recibirá un error que contiene este texto:
[El espacio de nombres '
<global namespace>
' ya contiene una definición para 'A
'].
Propina:
Para solucionar esto, puede usar la partial
palabra clave o cambiar uno de los nombres de clase.
¿Cómo trata el compilador de C # con clases parciales?
Si desmonta el programa anterior (usando IL Disassembler), verá que se eliminan los archivos A1.cs y A2.cs. Encontrará que la clase A está presente.
La clase A contendrá los métodos A1 y A2 en el mismo bloque de código. Las dos clases se fusionaron en una.
Resultado compilado de A1.cs y A2.cs: C #
internal class A
{
// Methods
public static void A1()
{
Console.WriteLine("A1");
}
public static void A2()
{
Console.WriteLine("A2");
}
}
Resumen
mantenga todo lo más limpio posible cuando trabaje con grandes clases, o cuando trabaje en un equipo, puede editar sin anular (o siempre comprometiendo cambios)
Si tiene una clase suficientemente grande que no se presta para una refactorización efectiva, separarla en varios archivos ayuda a mantener las cosas organizadas.
Por ejemplo, si tiene una base de datos para un sitio que contiene un foro de discusión y un sistema de productos, y no desea crear dos clases de proveedores diferentes (NO es lo mismo que una clase proxy, para ser claros), puede crear una sola clase parcial en diferentes archivos, como
MyProvider.cs - lógica central
MyProvider.Forum.cs: métodos que pertenecen específicamente al foro
MyProvider.Product.cs - métodos para productos
Es solo otra forma de mantener las cosas organizadas.
Además, como han dicho otros, es la única forma de agregar métodos a una clase generada sin correr el riesgo de que se destruyan sus adiciones la próxima vez que se regenere la clase. Esto es útil con código generado por plantilla (T4), ORM, etc.
Como alternativa a las directivas de precompilador.
Si usa directivas de precompilador (a saber #IF DEBUG
), entonces termina con un código de aspecto retorcido mezclado con su código de lanzamiento real.
Puede crear una clase parcial separada para contener este código y envolver toda la clase parcial en una directiva u omitir que el archivo de código se envíe al compilador (haciendo lo mismo).
Las referencias de servicio son otro ejemplo en el que las clases parciales son útiles para separar el código generado del código creado por el usuario.
Puede "extender" las clases de servicio sin sobrescribirlas cuando actualice la referencia de servicio.
Otro uso que vi es,
Extender una gran clase abstracta con respecto a la lógica de acceso a datos,
Tengo varios archivos con nombres Post.cs, Comment.cs, Pages.cs ...
in Post.cs
public partial class XMLDAO :BigAbstractClass
{
// CRUD methods of post..
}
in Comment.cs
public partial class XMLDAO :BigAbstractClass
{
// CRUD methods of comment..
}
in Pages.cs
public partial class XMLDAO :BigAbstractClass
{
// CRUD methods of Pages..
}
La mayoría de la gente comenta que partial
solo debe usarse para una clase que tiene un archivo de código generado o para interfaces. No estoy de acuerdo, y aquí está el por qué.
Por ejemplo, veamos la clase C # System.Math ... esa es la clase . No intentaría meter más de 70 métodos en el mismo archivo de código único. Sería una pesadilla mantenerlo.
Colocar cada método matemático en archivos individuales de clase parcial, y todos los archivos de código en una carpeta matemática en el proyecto, sería una organización significativamente más limpia.
Lo mismo podría / sería válido para muchas otras clases que tienen una gran cantidad de funcionalidad diversa. Por ejemplo, una clase para administrar la API PrivateProfile podría beneficiarse al dividirse en un conjunto limpio de archivos de clase parcial en una sola carpeta de proyecto.
Personalmente, también dividí lo que la mayoría de la gente llama clases "auxiliares" o "utilitarias" en archivos parciales individuales para cada método o grupo funcional de métodos. Por ejemplo, en un proyecto, la clase auxiliar de cadena tiene casi 50 métodos. Ese sería un archivo de código largo y difícil de manejar, incluso utilizando regiones. Es significativamente más fácil de mantener utilizando archivos de clase parciales individuales para cada método.
Solo tendría cuidado al usar clases parciales y mantener todo el diseño del archivo de código consistente durante todo el proyecto al hacer esto. Como colocar cualquier enumeración pública de clase y miembros privados de clase en un archivo Common.cs o de nombre similar en la carpeta, en lugar de distribuirlos entre los archivos a menos que sean específicos solo del archivo parcial en el que están contenidos.
Tenga en cuenta que cuando divide una clase en archivos separados también pierde la capacidad de usar la barra de división del editor de texto que le permite ver dos secciones diferentes de un archivo actual simultáneamente.
Las clases parciales permiten agregar funcionalidad a un programa diseñado de manera adecuada simplemente agregando archivos fuente. Por ejemplo, un programa de importación de archivos podría diseñarse para que uno pudiera agregar diferentes tipos de archivos conocidos agregando módulos que los manejen. Por ejemplo, el convertidor de tipo de archivo principal podría incluir una clase pequeña:
Clase pública parcial zzFileConverterRegistrar Registro de eventos (ByVal mainConverter como zzFileConverter) Sub registerAll (ByVal mainConverter como zzFileConverter) Registro RaiseEvent (mainConverter) End Sub Clase final
Cada módulo que desee registrar uno o más tipos de convertidor de archivos podría incluir algo como:
Clase pública parcial zzFileConverterRegistrar Private Sub RegisterGif (ByVal mainConverter as zzFileConverter) Me maneja. mainConverter.RegisterConverter ("GIF", GifConverter.NewFactory)) End Sub Clase final
Tenga en cuenta que la clase principal del convertidor de archivos no está "expuesta", solo expone una pequeña clase de código auxiliar a la que pueden engancharse los módulos adicionales. Existe un pequeño riesgo de conflictos de nomenclatura, pero si la rutina de "registro" de cada módulo de complementos se nombra de acuerdo con el tipo de archivo con el que trata, probablemente no deberían plantear un problema. Uno podría pegar un GUID en el nombre de la subrutina de registro si estuviera preocupado por tales cosas.
Editar / Anexo Para ser claros, el propósito de esto es proporcionar un medio por el cual una variedad de clases separadas puede informar a un programa o clase principal sobre ellas. Lo único que hará el convertidor de archivos principal con zzFileConverterRegistrar es crear una instancia y llamar al método registerAll que activará el evento Register. Cualquier módulo que desee enganchar ese evento puede ejecutar código arbitrario en respuesta a él (esa es la idea), pero no hay nada que un módulo pueda hacer al extender incorrectamente la clase zzFileConverterRegistrar que no sea definir un método cuyo nombre coincida con el de otra cosa. . Ciertamente, sería posible que una extensión escrita incorrectamente rompa otra extensión escrita incorrectamente, pero la solución para eso es que cualquiera que no quiera que su extensión se rompa simplemente la escriba correctamente.
Uno podría, sin usar clases parciales, tener un poco de código en algún lugar dentro de la clase del convertidor de archivos principal, que se parecía a:
RegisterConverter ("GIF", GifConvertor.NewFactory) RegisterConverter ("BMP", BmpConvertor.NewFactory) RegisterConverter ("JPEG", JpegConvertor.NewFactory)
pero agregar otro módulo convertidor requeriría ingresar a esa parte del código del convertidor y agregar el nuevo convertidor a la lista. El uso de métodos parciales ya no es necesario: todos los convertidores se incluirán automáticamente.
IModule
interfaz?
IModule
, podría usar un marco de plugins como MEF (solo uno de muchos), etc., etc.
Las clases parciales ayudaron recientemente con el control de código fuente donde varios desarrolladores estaban agregando a un archivo donde se agregaron nuevos métodos en la misma parte del archivo (automatizado por Resharper).
Estos empujes a git causaron conflictos de fusión. No encontré ninguna manera de decirle a la herramienta de fusión que tome los nuevos métodos como un bloque de código completo.
Las clases parciales a este respecto permiten que los desarrolladores se adhieran a una versión de su archivo, y podemos fusionarlas más tarde manualmente.
ejemplo
De MSDN :
1. En el momento de la compilación, los atributos de las definiciones de tipo parcial se fusionan. Por ejemplo, considere las siguientes declaraciones:
[SerializableAttribute]
partial class Moon { }
[ObsoleteAttribute]
partial class Moon { }
Son equivalentes a las siguientes declaraciones:
[SerializableAttribute]
[ObsoleteAttribute]
class Moon { }
Los siguientes se fusionan de todas las definiciones de tipo parcial:
Comentarios XML
interfaces
atributos de parámetros de tipo genérico
atributos de clase
miembros
2. Otra cosa, las clases parciales anidadas también pueden ser parciales:
partial class ClassWithNestedClass
{
partial class NestedClass { }
}
partial class ClassWithNestedClass
{
partial class NestedClass { }
}
Aquí hay una lista de algunas de las ventajas de las clases parciales.
Puede separar el código de diseño de la interfaz de usuario y el código de lógica empresarial para que sea fácil de leer y comprender. Por ejemplo, si está desarrollando una aplicación web con Visual Studio y agrega un nuevo formulario web, existen dos archivos de origen, "aspx.cs" y "aspx.designer.cs". Estos dos archivos tienen la misma clase con la palabra clave parcial. La clase ".aspx.cs" tiene el código de lógica de negocios, mientras que "aspx.designer.cs" tiene la definición de control de interfaz de usuario.
Cuando se trabaja con una fuente generada automáticamente, el código se puede agregar a la clase sin tener que volver a crear el archivo fuente. Por ejemplo, está trabajando con LINQ to SQL y crea un archivo DBML. Ahora, cuando arrastra y suelta una tabla, crea una clase parcial en designer.cs y todas las columnas de la tabla tienen propiedades en la clase. Necesita más columnas en esta tabla para enlazar en la cuadrícula de la interfaz de usuario, pero no desea agregar una nueva columna a la tabla de la base de datos para poder crear un archivo fuente separado para esta clase que tenga una nueva propiedad para esa columna y ser una clase parcial Eso afecta la asignación entre la tabla de la base de datos y la entidad DBML, pero puede obtener fácilmente un campo adicional. Significa que puede escribir el código por su cuenta sin meterse con el código generado por el sistema.
Más de un desarrollador puede escribir simultáneamente el código para la clase.
Puede mantener mejor su aplicación compactando clases grandes. Suponga que tiene una clase que tiene múltiples interfaces para poder crear múltiples archivos fuente dependiendo de los implementos de la interfaz. Es fácil de entender y mantener una interfaz implementada en la cual el archivo fuente tiene una clase parcial.
Cada vez que tengo una clase que contiene una clase anidada de cualquier tamaño / complejidad significativa, marco la clase como partial
y coloco la clase anidada en un archivo separado. Nombre el archivo que contiene la clase anidada usando la regla: [nombre de clase]. [Nombre de clase anidada] .cs.
El siguiente blog de MSDN explica el uso de clases parciales con clases anidadas para mantenimiento: http://blogs.msdn.com/b/marcelolr/archive/2009/04/13/using-partial-classes-with-nested-classes-for- mantenibilidad.aspx
Sé que esta pregunta es muy antigua, pero me gustaría agregar mi opinión sobre las clases parciales.
Una razón por la que personalmente uso clases parciales es cuando estoy creando enlaces para un programa, especialmente máquinas de estado.
Por ejemplo, OpenGL es una máquina de estados, hay un montón de métodos que se pueden cambiar globalmente, sin embargo, en mi experiencia, vincular algo similar a OpenGL donde hay tantos métodos, la clase puede superar fácilmente los 10k LOC.
Las clases parciales desglosarán esto para mí y me ayudarán a encontrar métodos rápidamente.
Las clases parciales se introducen principalmente para ayudar a los generadores de código, por lo que nosotros (usuarios) no terminamos perdiendo todo nuestro trabajo / cambios en las clases generadas como la clase .designer.cs de ASP.NET cada vez que regeneramos, casi todas las herramientas nuevas que generan el código LINQ, EntityFrameworks, ASP.NET usa clases parciales para el código generado, por lo que podemos agregar o alterar de forma segura la lógica de estos códigos generados aprovechando las clases y métodos parciales, pero tenga mucho cuidado antes de agregar cosas al código generado usando clases parciales es más fácil si rompemos la compilación pero peor si introducimos errores de tiempo de ejecución. Para más detalles verifique http://www.4guysfromrolla.com/articles/071509-1.aspx
Observo dos usos que no pude encontrar explícitamente en las respuestas.
Algunos desarrolladores usan comentarios para separar diferentes "partes" de su clase. Por ejemplo, un equipo podría usar la siguiente convención:
public class MyClass{
//Member variables
//Constructors
//Properties
//Methods
}
Con clases parciales, podemos ir un paso más allá y dividir las secciones en archivos separados. Como convención, un equipo puede sufijar cada archivo con la sección correspondiente. Entonces, en lo anterior tendríamos algo como: MyClassMembers.cs, MyClassConstructors.cs, MyClassProperties.cs, MyClassMethods.cs.
Como otras respuestas aludieron, si vale la pena dividir la clase o no, probablemente depende de qué tan grande sea la clase en este caso. Si es pequeño, probablemente sea más fácil tener todo en una clase magistral. Pero si alguna de esas secciones se hace demasiado grande, su contenido se puede mover a una clase parcial separada, para mantener ordenada la clase maestra. Una convención en ese caso podría ser dejar un comentario al decir algo como "Ver clase parcial" después del título de la sección, por ejemplo:
//Methods - See partial class
Esto es probablemente una ocurrencia rara, pero puede haber una colisión de espacio de nombres entre dos funciones de bibliotecas que desea usar. En una sola clase, a lo sumo podría usar una cláusula de uso para uno de estos. Para el otro necesitaría un nombre completo o un alias. Con clases parciales, dado que cada espacio de nombres y la lista de declaraciones de uso es diferente, uno podría separar los dos conjuntos de funciones en dos archivos separados.
using Library1 = The.Namespace.You.Need
oglobal::Root.Of.Namespace