代码之家  ›  专栏  ›  技术社区  ›  4thSpace wkw

如何创造。NET接口是否包含静态成员?

  •  12
  • 4thSpace wkw  · 技术社区  · 17 年前

    在。NET 3.5,我想创建一个单例接口:

    interface ISingleton <T>
    {
      public static T Instance {get;}
    }
    

    当然,这不起作用,但这是我想要的。有什么建议吗?

    编辑:我只是想让大家知道,所有singelton都有一个名为类类型Instance的静态属性。它总是在那里。接口将是表达这一点的明确方式。

    9 回复  |  直到 17 年前
        1
  •  12
  •   Matthew Brubaker    17 年前

    据我所知,接口不能是单例,因为它实际上并不存在。接口是实现必须遵循的契约。因此,实现可以是单例,但接口不能。

        2
  •  7
  •   Andrew Kennan    17 年前

    虽然我同意其他人的观点,即单例被过度使用,但你的问题的一个可能解决方案是提供一个抽象基类,其中包含派生单例的类型参数:

    public abstract class Singleton<T> where T : Singleton<T>
    {
      private static T _instance;
    
      public static T Instance
      {
        get { return _instance; }
        protected set { _instance = value; }
      }
    }
    

    任何从Singleton派生的类都将具有正确类型的静态Instance属性:

    public class MySingleton : Singleton<MySingleton>
    {
        static MySingleton()
        {
            Instance = new MySingleton();
        }
    
        private MySingleton() { } 
    }
    

    在使用这样的东西之前,你应该认真考虑是否需要单例,或者你是否更适合使用普通的静态类。

        3
  •  4
  •   Tim Jarvis    17 年前

    好吧,我把这个答案做成了维基,因为我只是想提供一个与你的问题相切的意见。

    我个人认为singleton被过度使用了,这是一个IMO实际上相当罕见的用例,在大多数情况下,静态类更适合用例,在其他情况下,工厂创建的imutable对象是最好的选择,实际的singleton比人们想象的要少得多。

    我不会有一个接口来描述这种常见模式,因为我实际上希望对单例的每一次使用都进行非常仔细和合理的考虑。

        4
  •  2
  •   yfeldblum    17 年前

    我只是想让大家知道,所有singelton都有一个名为类类型Instance的静态属性。它总是在那里。接口将是表达这一点的明确方式。

    写一个单元测试。

        5
  •  2
  •   tsimon    17 年前

    我知道这不是你的问题,但你有多少单身汉需要一个接口?在我看来,这听起来像是糟糕的设计——你能清楚地解释为什么这些类应该是单例而不是实例吗?如果你的答案是记忆,我建议你过度思考你的应用程序,如果你真的很担心,可以看看轻量级模式(或者一个简单的工厂模式)。很抱歉没有直接回答这个问题,但这听起来不是个好主意。

        6
  •  1
  •   devio    17 年前

    此外,正如您所说,它不起作用,您将如何使用此接口和实现类?

    您可以尝试使用Factory风格的界面

    interface ISingletonFactory<T>
    {
        public T Instance {get;}
    }
    
    public class SingletonFactory: ISingletonFactory<Singleton>
    {
        public Singleton Instance {get { return Singleton.Instance;}}
    }
    
    public class Singleton
    {
        private Singleton foo;
        public static Singleton Instance { get { return foo; } }
    }
    
        7
  •  0
  •   Stefano Driussi    17 年前

    鉴于接口面向对象编程的经典概念将其定义为实现类之间的契约,你不能向其中添加静态方法这样的东西。如果你能这样做,你将以一个更类似于抽象类的东西结束,在这个抽象类中,你有你的类的部分实现和扩展类所需的其他部分。

        8
  •  0
  •   Yes - that Jake.    17 年前

    正如所指出的,你不能这样做,你有充分的理由不应该这样做。

    我过去实现的方法创建了一个接口和一个实现该接口的抽象基类。它看起来像这样:

    public interface IMyCompanySetting
    {
        XmlNode Serialize();
        IMyCompanySetting Deserialize(XmlNode pattern);
        string SettingName { get; }
    

    string键{get;} 对象设置值{get;set;} 设置范围范围{get;set;} }

    public abstract class MyCompanySettingBase : IMyCompanySetting
    {
        public MyCompanySettingBase() {}
        public MyCompanySettingBase(XmlNode pattern)
        {
            Deserialize(pattern);
        }
        #region IMyCompanySetting Members
    
        public abstract XmlNode Serialize();
        public abstract IMyCompanySetting Deserialize(XmlNode pattern);
        public abstract string SettingName{ get; }
    public abstract string Key { get; }
        public abstract SettingScope Scope{ get; set; }
        public abstract object SettingValue{ get; set; }
    
        #endregion
    
    public static XmlNode WrapInSettingEnvelope(XmlNode innerNode, IMyCompanySetting theSetting)
    {
        // Write the top of the envelope.
        XmlTextWriter xtw = null;
        MemoryStream theStream = OpenSettingEnvelope(theSetting, ref xtw);
    
        // Insert the message.
        xtw.WriteNode(new XmlTextReader(innerNode.OuterXml, XmlNodeType.Element, null), true);
    
        // Close the envelope.
        XmlNode retNode = CloseSettingEnvelope(xtw, theStream);
        return retNode;
    
    }
    
    public static MemoryStream OpenSettingEnvelope(IMyCompanySetting theSetting, ref XmlTextWriter theWriter)
    {
        MemoryStream theStream = new MemoryStream();
        theWriter = new XmlTextWriter(theStream, Encoding.ASCII);
        System.Type messageType = theSetting.GetType();
    
        string[] fullAssembly = messageType.Assembly.ToString().Split(',');
        string assemblyName = fullAssembly[0].Trim();
    
        theWriter.WriteStartElement(theSetting.SettingName);
        theWriter.WriteAttributeString("type", messageType.ToString());
        theWriter.WriteAttributeString("assembly", assemblyName);
        theWriter.WriteAttributeString("scope", ConfigurationManager.ScopeName(theSetting.Scope));
    
        return theStream;
    }
    
    public static XmlNode CloseSettingEnvelope(XmlTextWriter xtw, MemoryStream theStream)
    {
        XmlDocument retDoc = new XmlDocument();
        try
        {
            // Close the envelope.
            xtw.WriteEndElement();
            xtw.Flush();
    
            // Return the node.
            string xmlString = Encoding.ASCII.GetString(theStream.ToArray());
            retDoc.LoadXml(xmlString);
        }
        catch (XmlException)
        {
            string xmlString = Encoding.ASCII.GetString(theStream.ToArray());
            Trace.WriteLine(xmlString);
            retDoc.LoadXml(@"<error/>");
        }
        catch (Exception)
        {
            retDoc.LoadXml(@"<error/>");
        }
        return retDoc.DocumentElement;
    }
    
    }
    
        9
  •  0
  •   Thaina Yu    5 年前

    两年前就有人支持这项提议

    https://github.com/dotnet/csharplang/issues/1711

    但是,是的,目前还不可能,特别是在.NET 3.5中不可能