How to associate constants with an interface in C#

2019-06-15 00:48发布

Some languages let you associate a constant with an interface:

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?

8条回答
Root(大扎)
2楼-- · 2019-06-15 01:02

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);
查看更多
Melony?
3楼-- · 2019-06-15 01:06

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";
}
查看更多
forever°为你锁心
4楼-- · 2019-06-15 01:07

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
}
查看更多
不美不萌又怎样
5楼-- · 2019-06-15 01:08

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.

查看更多
beautiful°
6楼-- · 2019-06-15 01:17

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.

查看更多
Fickle 薄情
7楼-- · 2019-06-15 01:18

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.

查看更多
登录 后发表回答