c# - optimizar - cuantas consultas por segundo soporta mysql
Devuelve uno de los dos posibles objetos de diferentes tipos que comparten un método. (6)
¿Por qué no tener una clase base que tiene Output
definida. Luego regresa la base.
public abstract class BaseType {
public abstract void Output();
}
Tanto los Articles
como el Questionaire
deben heredar este tipo de base.
public class Articles : BaseType {
// Output method here
}
public class Questionaire : BaseType {
// Output method here
}
Entonces puedes hacer:
public static BaseType Choose(int x, string name)
{
if (x == 1)
{
Articles art = new Articles(name);
return art;
}
if (x == 2)
{
Questionnaire ques = new Questionnaire(name);
return ques;
}
}
También puede lograr esto a través de una interface
.
public interface IInterface {
void Output();
}
public class Articles : IInterface {
// Output method here
}
public class Questionaire : IInterface {
// Output method here
}
A continuación, tendrá que modificar el método Choose para devolver IInterface
lugar de BaseType
. Lo que elijas depende de ti.
Nota: incluso si no puede cambiar las clases originales, aún puede usar estos enfoques antes de recurrir a la dynamic
proporcionando clases de envoltura que implementan la interfaz y hereda las llamadas originales o hacia adelante al método correspondiente:
public class ArticlesProxy : Articles, IInterface
{
public ArticlesProxy(string name) : base(name){}
}
public class QuestionaireProxy : Questionaire, IInterface {
Questionaire inner;
public QuestionaireProxy(string name) { inner = new Questionaire(name); }
public void Output() { inner.Output();}
}
Tengo 2 clases:
public class Articles
{
private string name;
public Articles(string name)
{
this.name = name;
}
public void Output()
{
Console.WriteLine("The class is: " + this.GetType());
Console.WriteLine("The name is: " + name);
}
}
Y
public class Questionnaire
{
private string name;
public Questionnaire(string name)
{
this.name = name;
}
public void Output()
{
Console.WriteLine("The class is: " + this.GetType());
Console.WriteLine("The name is: " + name);
}
}
Quiero escribir un método que tome un número entero (1 significa que los Articles
deben devolverse, 2 significa Questionnaire
) y un nombre.
Este método debe devolver una instancia de una de esas dos clases:
public [What type??] Choose(int x, string name)
{
if (x == 1)
{
Articles art = new Articles(name);
return art;
}
if (x == 2)
{
Questionnaire ques = new Questionnaire(name);
return ques;
}
}
¿Qué tipo de devolución debo usar, para poder llamar a Output()
en el resultado?
A menos que compartan la misma clase base o interfaz, está bastante atascado con el object
o la dynamic
.
La forma más flexible de resolver este problema es escribir una interfaz y una clase base abstracta que lo implemente. De esta manera, tiene la libertad de derivar una clase de la clase base o de implementar la interfaz directamente, si la clase base no satisface sus necesidades en un caso muy especial o si una clase se deriva de otra clase ya. También hacer el método de Output
virtual; esto le permite anularlo si es necesario. También haga el name
protegido; esto te permite usarlo en clases derivadas
public interface IHasOutput
{
void Output();
}
public abstract class OutputBase : IHasOutput
{
protected string _name;
public OutputBase(string name)
{
_name = name;
}
#region IHasOutput Members
public virtual void Output()
{
Console.WriteLine("The class is: " + this.GetType());
Console.WriteLine("The name is: " + _name);
}
#endregion
public static IHasOutput Choose(int x, string name)
{
switch (x) {
case 1:
return new Articles(name);
case 2:
return new Questionnaire(name);
default:
return null;
}
}
}
public class Articles : OutputBase
{
public Articles(string name)
: base(name)
{
}
}
public class Questionnaire : OutputBase
{
public Questionnaire(string name)
: base(name)
{
}
}
ACTUALIZAR
Otra forma muy sencilla de resolver el problema es anular ToString
:
public override string ToString()
{
return String.Format("The class is: {0}/r/nThe name is: {1}",
this.GetType(), _name);
}
Usted lo llamaría así:
object obj = Factory.Choose(1, "Test");
Console.WriteLine(obj);
No se requiere interfaz ni clase base! Bueno, para ser precisos, la clase base es object
por supuesto.
Las respuestas proporcionadas aquí son excelentes, pero una cosa que no me gusta es el parámetro x
que elige qué tipo se debe crear. Eso crea el uso del número mágico , que puede convertirse en un dolor de cabeza incluso para ti más adelante.
Puede aprovechar los genéricos aquí, es decir, hacer un método Choose
:
public static T Choose<T>(string name)
// type constraint to ensure hierarchy.
where T : BaseClass // BaseClass have common functionality of both class.
{
// Unfortunately you can''t create instance with generic and pass arguments
// to ctor. So you have to use Activator here.
return (T)Activator.CreateInstance(typeof(T), new[] { name });
}
Uso:
Articles article = ClassWithChooseMethod.Choose<Articles>("name");
Questionnaire questionnaire = ClassWithChooseMethod.Choose<Questionnaire>("name2");
Editar
Como @ OlivierJacot-Descombes mencionó en el comentario x
que elige el tipo podría ser una entrada del usuario. En ese caso puedes crear enum
con los valores respectivos:
enum ArticleType {
Articles = 1,
Questionnaire = 2
}
Y tiene sobrecarga de Choose
:
public static BaseClass Choose(ArticleType type, string name) {
switch (type) {
case ArticleType.Articles:
return ClassWithChooseMethod.Choose<Articles>(name);
case ArticleType.Questionnaire:
return ClassWithChooseMethod.Choose<Questionnaire>(name);
default:
return default(BaseClass);
}
}
y uso:
var obj = ClassWithChooseMethod.Choose((ArticleType)userInput, "some name");
Esto le da la posibilidad de mantener su código más limpio y útil para el mantenimiento futuro (por ejemplo, puede cambiar la lógica de creación de clases en Choose
).
Puede que te interese leer más sobre el patrón de fábrica .
Qué tal algo como esto:
public interface IHasOutput
{
void Output();
}
public class Articles : IHasOutput
public class Questionnaire : IHasOutput
y entonces:
public static IHasOutput Choose...
Por supuesto, puede llamar a su interfaz como desee, aparte de IHasOutput
, simplemente no sé cómo llamarlo. Para eso son las interfaces. Dos implementaciones concretas diferentes que comparten una interfaz común. Ahora cuando lo llamas puedes hacer esto:
var entity = MyClass.Choose(1, "MyName");
entity.Output();
Y no importa qué implementación concreta se devuelva. Ya sabes que implementa una interfaz común.
Tienes 3 opciones:
1) Haga que el cuestionario y el artículo se hereden de la misma clase base y haga que el tipo de esa clase base sea el tipo de retorno de su método.
2) Haz tu tipo de devolución de Objeto.
3) Haz que tu tipo de devolución sea Dinámico.