web-dev-qa-db-ja.com

定数をC#のインターフェイスに関連付ける方法は?

一部の言語では、定数をインターフェイスに関連付けることができます。

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言語はありますか?
19
ChrisW

3番目の質問に答えるには:

C#ではできませんが、インターフェイスに関連付けられた定数を定義できる別の.NET言語はありますか?

C++/CLIでは、インターフェイスでliteral値を定義できます。これは、C#のstatic const値に相当します。

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値タイプはおそらく列挙である方が良いでしょう。

17
MattDavey

定数を保存する場所が必要な場合は、静的クラスを使用します。

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

これが(少なくとも1つの)共通の標準です。

13
Servy

定数は、動作プロトコルのみを定義する型には理論的には属さない実装ファセットであるため、C#ではインターフェイスで定数を使用できません。

私はJava=人々がインターフェイスでconstフィールドを許可していると思います列挙型。

「DOMインターフェースの標準的なバインディング」の意味がわかりません。 C#はブラウザーでは実行されません。

つまり、定数は構造体や列挙型(数値の場合)などの別の場所に配置する必要があります。おそらく、ある種の命名規則に従うことが役立つでしょう。インターフェイスがIFooBarの場合、定数を含む構造体はIFooSetttingsまたはIFooValuesまたは適切なものと呼ばれる可能性があります。

C#とVB.NET以外のCLR言語は知りませんが、VBはこれを許可していません(しばらくの間ですが)。

7
kprobst

Get onlyプロパティを追加し、定義のconstでバックアップしました。

public interface IFoo
{
    string ConstValue { get; }
}

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

私は常に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
}
4
Jay Schroeder

抽象クラスは、インターフェイスが行うすべてのことを行い(typeof(T).IsInterfaceテストをパスすることを除いて)、定数を許可します。

インターフェースに埋め込まれた定数(または列挙型)への反対は見当違いです。それは命名の問題です。定数が意味を持つ非常に正確なコンテキストで定数に名前を付けることは、コンテキスト外で名前を付けるよりも優れています。

1
Chris F Carroll

カスタム属性を使用できます。

[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);
0

メソッドパラメータや戻り値を考慮して定義してみてください

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();
}
0
icar0