【问题标题】:Nested static class C#嵌套静态类 C#
【发布时间】:2011-09-11 18:32:35
【问题描述】:

我想知道我是否可以获得称为静态类的静态方法的对象 例如:

public class Person
{
    private static class TelephoneLine
    {
        public static string sharedString = string.Empty;
        public static void NotifyOnCall()
        {
            //notify if someone call this person
        }
        public static void Comunicate(Person comunicateWith, string message)
        {
            sharedString = "Sender: " /* Object which called that method */ + " To: " + comunicateWith.Name +
                           " said: " + message;
        }
    }
    public Person(string name)
    {
        Name = name;
    }
    string Name;
    public void CallTo(Person person, string message)
    {
        TelephoneLine.Comunicate(person, message);
    }
    public void ShowCall()
    {
        Console.Write(TelephoneLine.sharedString);
    }
}

}

那么除了在 ThelephoneLine.Comunicate(this, comunicateWith, msg) 的参数中传递它之外,是否有可能获得“Sender”?

【问题讨论】:

  • 这个问题与(嵌套的)静态类有什么关系?

标签: c# nested-class static-class


【解决方案1】:

可以使用堆栈爬取(前提是您防止静态方法被内联),但这通常是个坏主意。

Retrieving the calling method name from within a method

如果可以的话,出于调试目的这样做。这样做是因为您懒得将它显式地写入您的正常程序流程中,这是非常糟糕的设计。所以在你的情况下,我强烈建议手动传递它。


有点离题,但我很确定您的课程不应该是静态的。静态方法适用于简单的无副作用函数(参见 MathEnumerable 以获得良好的示例)。你的TelephoneLine 至少应该是一个单例,但 IMO 你应该简单地使用依赖注入并注入它的单个实例。

【讨论】:

    【解决方案2】:

    简单的答案是否定的。许多 .NET 自己的事件(WinForms 或 ASP 中的 Clicked 等)要求您传递“发送者”参数。

    您可以查看堆栈以获取方法的名称,甚至可以获取调用者的类型,但您肯定无法获取调用该函数的特定对象。

    【讨论】:

      【解决方案3】:

      一种方法是在人员和服务之间定义一个通用接口,并使用它的合同来传递数据:

      通用解决方案可能对嵌套的私有服务类来说太过分了,但您可能希望扩展以后可以拨打电话的内容并将其重构为公开,例如自动服务调用等。

      public interface ICallable { string CallerIdString(); }
      
      public class Person : ICallable
      {
          private static class TelephoneLine
          {
              public static string sharedString = string.Empty;
              public static void NotifyOnCall()
              {
                  //notify if someone call this person
              }
              public static void Comunicate<TCaller>(TCaller Caller, Person comunicateWith, string message) where TCaller : ICallable
              {
                  sharedString = "Sender: " + Caller.CallerIdString() + " To: " + comunicateWith.Name +
                                 " said: " + message;
                                 sharedString.Dump();
              }
          }
          public Person(string name)
          {
              Name = name;
          }
          string Name;
          public void CallTo(Person person, string message)
          {
              TelephoneLine.Comunicate<Person>(this, person, message);
          }
          public void ShowCall()
          {
              Console.Write(TelephoneLine.sharedString);
          }
      
          public string CallerIdString() { return this.Name;}
      }
      

      【讨论】:

        【解决方案4】:

        TelephoneLine 类不应真正由 Person 拥有(它们由电话公司拥有!)并且它们真的不应该是静态的(静态 == 代码气味)。

        class TelephoneLine
        {
          public TelephoneLine (Person sender, Person receiver)
          {
            m_sender = sender;
            m_receiver = receiver;
          }
        
          public void Send (Person from, String message)
          {
            if (from == sender)
            {
               output "From: " + m_sender + " To: " + m_receiver + " Message: " + message;
            }
            else
            {
               output "From: " + m_receiver + " To: " + m_sender + " Message: " + message;
            }
          }
        
          Person m_sender, m_receiver;
        };
        
        class Person
        {
          public void MakeCall (Person receiver, string message)
          {
             TelephoneLine line = new TelephoneLine (this, receiver);
             line.Send (this, message);
          }
        }
        

        事实上,TelephoneLine 对象应该归其他东西所有:

        class Exchange
        {
          public TelephoneLine MakeCall (Person from, Person to)
          {
            // check that 'to' can receive call first!
            return new TelephoneLine (from, to);
          }
        };
        
        class Person
        {
          public void MakeCall (Person receiver, string message)
          {
             TelephoneLine line = the_exchange.MakeCall (this, receiver);
             if (line != null)
             {
               line.Send (this, message);
             }
             // else, receiver not listening!
          }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-05-11
          • 2015-01-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多