Как вы определяете метод в классе в его экземпляре? - PullRequest
2 голосов
/ 17 марта 2009

Это, наверное, очень легко, но я в тупике. Я хотел бы создать класс общего назначения, который будет использоваться несколько раз в моей программе. Я хочу, чтобы это было очень легко и очень быстро.

Для очень простого примера в C #:

public class SystemTest
{ 
   public TestMethod(string testString)
   {
      if(testString == "blue")
      {
         RunA();
      }
      else if(testString == "red")
      {
         RunB();
      }
      else if(testString == "orange")
      {
         RunA();
      }
      else if(testString == "pink")
      {
         RunB();
      }
   }

   protected void RunA() {}
   protected void RunB() {}       
}

Я хочу, чтобы RunA () и RunB () определялись и управлялись объектом, экземпляром которого является этот класс. Это будет полностью зависеть от класса экземпляра SystemTest объекта, чтобы выяснить, что будут делать RunA () и RunB (). Как ты это делаешь?

Я не хочу, чтобы объект экземпляра всегда наследовал этот класс SystemTest, и я бы хотел, чтобы он работал очень быстро. Единственное, о чем я думаю, - это сложные, ресурсоемкие вещи. Я знаю, что есть более простой способ сделать это.


Редактировать: Как правило, который работает быстрее, делегат или метод интерфейса на ответы ниже?

Ответы [ 6 ]

8 голосов
/ 17 марта 2009

Вы можете:

public class SystemTest
{ 
   Action RunA;
   Action RunB;
   public SystemTest(Action a, Action b)
   {
      RunA = a;
      RunB = b;
   }
   //rest of the class
}
6 голосов
/ 17 марта 2009

Звучит так, будто вам нужен интерфейс, например:

interface ITestable {
    void RunA();
    void RunB();
}

и вы передаете это (либо в SystemTest ctor, либо в TestMethod). Вызывающие классы могут (например) реализовать ITestable и вызвать TestMethod (this, someString).

В качестве альтернативы может быть метод расширения? кстати, string arg может быть перечислением?

public interface ITestable {
    void RunA();
    void RunB();
}
public static class SystemTest
{ 
   public static void TestMethod(this ITestable item, string testString)
   {
      if(testString == "blue")
      {
         item.RunA();
      }
      else if(testString == "red")
      {
          item.RunB();
      }
      else if(testString == "orange")
      {
          item.RunA();
      }
      else if(testString == "pink")
      {
          item.RunB();
      }
   }
}

Тогда вызывающие просто реализуют ITestable, и любой может вызвать foo.SomeMethod(color); для экземпляра foo.

0 голосов
/ 17 марта 2009

Зачем использовать класс, когда все, что вам нужно, это структура данных?

Dictionary<string, Action> MethodMap = new Dictionary<string, Action>
{
   { "red", RedMethod },
   { "blue", BlueMethod },
   { "green", GreenMethod },
   { "yellow", YellowMethod }
};

Тогда вам не нужен класс для запуска метода; просто

Method[key];

будет делать.

0 голосов
/ 17 марта 2009

Представьте методы RunA, RunB как события, чтобы к ним мог присоединиться любой вызывающий объект. Ex.:

public class SystemTest
{ 
   public TestMethod(string testString)
   {
      if(testString == "blue")
      {
         RunA();
      }
      else if(testString == "red")
      {
         RunB();
      }
      else if(testString == "orange")
      {
         RunA();
      }
      else if(testString == "pink")
      {
         RunB();
      }
   }

   protected event Action RunA;
   protected event Action RunB;       
}
0 голосов
/ 17 марта 2009

Другая опция, не упомянутая, - это изменение RunA и RunB на события вместо методов. События в .net достаточно легки и быстры и потенциально могут соответствовать вашей модели использования, не требуя создания нового класса для определения поведения для каждого экземпляра / использования.

Учитывая, что вам нужно поведение, основанное на экземплярах, вам нужно будет переработать его, чтобы использовать либо делегаты или события, либо передать один базовый класс или интерфейс и вызвать методы непосредственно для этого.

0 голосов
/ 17 марта 2009

Если есть только ограниченные варианты цвета, такие как синий, красный, оранжевый и розовый. Вы можете создать перечисление как

public enum Color 
{
   Blue,
   Red,
   Orange,
   Pink
}

И используйте это перечисление с оператором switch с любым из упомянутых здесь решений. Компилятор обрабатывает перечисления как целые числа, так как вам нужна производительность. Целочисленное сравнение более эффективно, чем сравнение строк.

switch (color)
{
case Color.Blue:
case Color.Orange: 
                   RunA();
                   break;
case Color.Red:
case Color.Pink:   RunB();
                   break;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...