How to associate constants with an interface in C#?

人盡茶涼 提交于 2019-12-01 13:52:58

问题


Some languages let you associate a constant with an interface:

  • A Java example
  • A PhP example

The W3C abstract interfaces do the same, for example:

// Introduced in DOM Level 2:
interface CSSValue {

  // UnitTypes
  const unsigned short      CSS_INHERIT                    = 0;
  const unsigned short      CSS_PRIMITIVE_VALUE            = 1;
  const unsigned short      CSS_VALUE_LIST                 = 2;
  const unsigned short      CSS_CUSTOM                     = 3;

  attribute DOMString       cssText;
  attribute unsigned short  cssValueType;
};

I want to define this interface such that it can be called from C#.

Apparently C# cannot define a constant associated with an interface.

  • What is the usual way to translate such an interface to C#?
  • Are there any 'canonical' C# bindings for the DOM interfaces?
  • Although C# cannot, is there another .NET language which can define constants associated with an interface?

回答1:


To answer your third question:

Although C# cannot, is there another .NET language which can define constants associated with an interface?

C++/CLI allows you to define literal values in an interface, which are equivalent to static const values in C#.

public interface class ICSSValue
{
public:
    literal short CSS_INHERIT = 0;
    literal short CSS_PRIMITIVE_VALUE = 1;
    literal short CSS_VALUE_LIST = 2;
    literal short CSS_CSS_CUSTOM = 3;

    property DOMString^ cssText;
    property ushort cssValueType;
}

You could then access the values via C#:

public static void Main()
{
    short primitiveValue = ICSSValue.CSS_PRIMITIVE_VALUE;

    Debug.Assert(primitiveValue == 1);
}

See this page on MSDN for more details.

Disclaimer: The design decision to disallow constant values in interfaces was a good one. An interface which exposes implementation details is most likely a leaky abstraction. In this example CSS Value Type is probably better off being an enumeration.




回答2:


If you want a place to store your constants I would use a static class:

public static class MyConstants
{
    public const int first = 1;
    public const int second = 2;
    public const string projectName = "Hello World";
}

That is (at least one) common standard.




回答3:


C# doesn't allow constants in interfaces because a constant is an implementation facet which theoretically does not belong in a type that only defines a behavior protocol.

I suspect the Java folks allow const fields in interfaces either because an interface is treated internally as some kind of abstract class, or because they needed that to make up for some deficiency in the type system, like enums.

I'm not sure what you mean by "canonical bindings for the DOM interfaces". C# does not run in a browser.

That said, you'll need to put your constants somewhere else, like a struct, or an enum (if they are numeric). Perhaps following some kind of naming convention would help -- if your interface is IFooBar then maybe the struct that contains your constant could be called IFooSetttings or IFooValues or whatever is appropriate.

I don't know any CLR languages other than C# and VB.NET, but I'm pretty sure VB doesn't allow this (although it's been a while).




回答4:


I added a Get only property and backed it up with a const in the definition.

public interface IFoo
{
    string ConstValue { get; }
}

public class Foo : IFoo
{
    public string ConstValue => _constValue;
    private string _constValue = "My constant";
}



回答5:


I use SO all the time but this is my first ever post here. I found this post, trying to solve the same problem. When I saw the post on using a static class (by Servy) it got me thinking about solving this by embedding the Interface inside that static class.

// define an interface with static content
public static class X {
    // define the interface to implement
    public interface Interface {
        string GetX();
    }

    // static content available to all implementers of this interface
    public static string StandardFormat(object x) {
        return string.Format("Object = {0}", x.ToString());
    }
}

// Implement the interface
public class MyX : X.Interface {
    public override string ToString() {
        return "MyX";
    }

    #region X.Interface Members

    public string GetX() {
        // use common code defined in the "interface"
        return X.StandardFormat(this);
    }

    #endregion
}



回答6:


An abstract class will do everything an interface will do (well, apart from pass a typeof(T).IsInterface test) and allow constants.

The objection to constants (or enums) embedded in interfaces is misplaced. It's a naming issue. Naming constants in the very precise context where they have meaning is better than naming them out of context.




回答7:


Try define it thought method parameters and/or returned values

public enum IFIleValue
{
    F_OK = 0,
    F_WRONG_NAME = -1,
    F_ERROR_OBJECT_DATA = -2,
};

public interface IFile
{
     IFIleValue New(String Name=null);
     IFIleValue Open(String Path);
     IFIleValue Save();
     IFIleValue SaveAs(String Path);
     IFIleValue Close();
}



回答8:


A custom attribute can be used:

[Constant("CSS_INHERIT", 0)]
[Constant("CSS_PRIMITIVE_VALUE", 1)]
public interface BlaBla

The custom attribute class could look like:

[AttributeUsage(AttributeTargets.Interface, AllowMultiple = true, Inherited = false)]
public class ConstantAttribute: Attribute
{
    public ConstantAttribute(string key, object value)
    {
        // ...
    }
}

Constants can be retrieved using

object[] attributes = typeof(BlaBla).GetCustomAttributes(typeof(ConstantAttribute),
    inherit: false);


来源:https://stackoverflow.com/questions/12752364/how-to-associate-constants-with-an-interface-in-c

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!