31

某些语言允许您将常量与接口相关联:

W3C 抽象接口也是如此,例如:

// 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;
};

我想定义这个接口,以便可以从 C# 调用它。

显然 C# 无法定义与接口关联的常量。

  • 将这样的接口转换为 C# 的常用方法是什么?
  • DOM 接口是否有任何“规范”C# 绑定?
  • 尽管 C# 不能,但是否有另一种 .NET 语言可以定义与接口关联的常量?
4

10 回答 10

23

我添加了一个 Get only 属性并在定义中使用 const 对其进行备份。

public interface IFoo
{
    string ConstValue { get; }
}

public class Foo : IFoo
{
    public string ConstValue => _constValue;
    private string _constValue = "My constant";
}
于 2018-04-06T11:35:24.670 回答
20

回答你的第三个问题:

尽管 C# 不能,但是否有另一种 .NET 语言可以定义与接口关联的常量?

C++/CLI 允许您literal在接口中定义值,这些值等效static const于 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;
}

然后,您可以通过 C# 访问这些值:

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

    Debug.Assert(primitiveValue == 1);
}

有关更多详细信息,请参阅MSDN 上的此页面。

免责声明:在接口中不允许使用常量值的设计决定是一个很好的决定。暴露实现细节的接口很可能是一个泄漏的抽象。在此示例中,CSS 值类型可能最好是枚举。

于 2012-10-05T19:22:02.667 回答
18

如果你想要一个地方来存储你的常量,我会使用一个静态类:

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

那是(至少一个)通用标准。

于 2012-10-05T18:56:23.773 回答
7

C# 不允许在接口中使用常量,因为常量是一个实现方面,理论上不属于仅定义行为协议的类型。

我怀疑 Java 人员允许在接口中使用 const 字段,或者因为接口在内部被视为某种抽象类,或者因为他们需要它来弥补类型系统中的某些缺陷,例如枚举。

我不确定您所说的“DOM 接口的规范绑定”是什么意思。C# 不在浏览器中运行。

也就是说,您需要将常量放在其他地方,例如结构或枚举(如果它们是数字)。也许遵循某种命名约定会有所帮助——如果你的接口是IFooBar那么可能包含你的常量的结构可以被调用IFooSetttings,或者IFooValues任何合适的。

除了 C# 和 VB.NET,我不知道任何 CLR 语言,但我很确定 VB 不允许这样做(尽管已经有一段时间了)。

于 2012-10-05T19:02:20.260 回答
4

我一直使用 SO,但这是我第一次在这里发帖。我找到了这篇文章,试图解决同样的问题。当我看到关于使用静态类的帖子(由 Servy 撰写)时,我开始考虑通过将接口嵌入到该静态类中来解决这个问题。

// 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
}
于 2017-12-16T13:08:56.840 回答
3

C# 8 现在允许在interface定义中使用常量。

于 2021-05-04T19:57:32.283 回答
1

一个抽象类会做接口会做的所有事情(好吧,除了通过typeof(T).IsInterface测试)并允许使用常量。

反对嵌入接口中的常量(或枚举)是错误的。这是一个命名问题。在它们有意义的非常精确的上下文中命名常量比在上下文中命名它们更好。

于 2015-02-13T11:34:52.820 回答
1

遇到了同样的问题 - 需要在接口中定义常量。发现了另一种可能性:通过在接口上使用扩展方法。像这样:

public interface IFoo
{
    // declarations
}
 
public static class IFooExtensions
{
    public static int Bar(this IFoo x) => 50;
}

但是,这将需要接口实例从中获取常量:

IFoo foo;
foo.Bar();

你也可以在接口实现中使用这个常量:

public class Foo: IFoo
{
    public Foo() {
        var x = this.Bar();
    }
}  
于 2020-11-12T15:23:54.697 回答
-1

尝试定义方法参数和/或返回值

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();
}
于 2016-05-25T08:23:31.600 回答
-1

可以使用自定义属性:

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

自定义属性类可能如下所示:

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

可以使用检索常量

object[] attributes = typeof(BlaBla).GetCustomAttributes(typeof(ConstantAttribute),
    inherit: false);
于 2019-01-27T08:46:45.937 回答