28

これがばかげた質問かどうかはわかりませんが、私はこれに気づきました。

public interface IActivityDao : IDao<Activity>
{
    IList<Activity> GetAllSinceSequence(long sequence, int count);
}

public class ActivityDao : AbstractNHibernateDao<Core.Domain.Activity>, IActivityDao
{        
    public IList<Activity> GetAllSinceSequence(long sequence, int maxRecords)
    {

    }
}

実装内で、2番目のパラメーターを「maxRecords」と呼びました。ただし、インターフェイスでは、「カウント」として定義されています。コンパイラーは、実装されたインターフェースを引き続き考慮します。これは優れていますが、少しあいまいになる可能性があります。明らかに、パラメータの1つを他のパラメータと一致するように名前変更する必要があります。

名前を変更する前に少し遊んだところ、何か面白いことに気づきました。インターフェイスを次のように宣言することは許可されていません。

public interface IActivityDao : IDao<Activity>
{
    IList<Activity> GetAllSinceSequence(long, int);
}

これは、コンパイラがC#の構文に対して過度に保護しているだけですか?コードを読みやすくする以外に、インターフェイスのメソッドのパラメータ名はどのような目的に役立ちますか?パラメータ名が実装に強制されていない場合、あいまいさを招くように思われます。

4

6 に答える 6

46

実装を明確にし、参照するために、インターフェイス宣言でパラメータ名が必要です。誰かがあなたのインターフェースを使用していた場合、メソッドパラメーターの名前は自己文書化されることを意図しているため、インターフェースの利用者はメソッドに何を渡すかを理解します(たとえば、IntelliSenseを介してメソッドの説明を表示する場合)

はい、インターフェースを実装するときに、パラメーターに任意の名前を付けることができます。

于 2012-09-04T23:45:54.980 に答える
10

歴史。これは、COMが世界を支配していた.NETのごく初期の時代にまでさかのぼります。当時、 COMと相互運用できることは非常に重要でした。まったく新しいスタイルのプログラミングを採用するために、すべてを捨てることはありませんでした。

これにより、COM相互運用機能は一般的に.NETで強力にサポートされました。インターフェイスメソッドの名前付き引数が必要なだけでなく、型ライブラリにはそれらが必要です。

興味深いコーナーケースは、永遠にC ++/CLI言語です。宣言でパラメーター名を省略する機能など、多くのC++構文規則を採用しました。言い換えれば、これは合法です:

    public interface class IFoo
    {
        void bar(int, long, double);
    };

タイプライブラリエクスポータは、次の宣言を生成します。

    HRESULT bar(
                    [in] long p1, 
                    [in] long p2, 
                    [in] double p3);

IntelliSenseによって自動生成されたように、C#クラスでインターフェイスを実装した場合の結果は非常に似ています。

class FooImpl : cpptemp36.IFoo {
    public void foo(int __p1, int __p2, double __p3) {
        throw new NotImplementedException();
    }
}

これは誰も幸せにしません。

于 2012-09-05T00:19:57.907 に答える
2

これを聞いてみましょう。パラメーター名なしでメソッドシグネチャを定義できる.netFrameworkの他の場所はありますか?

結局のところ、すべてのことが可能ですが、ほとんどのことが理由であります。この場合、これがフレームワークとコンパイラの設計の限界であると想像します。それは本当に重要ですか?

結局のところ、使用する契約を定義しているので、実際にそこにあることが期待されます。

于 2012-09-04T23:47:55.477 に答える
2

コード品質の新しい世界では、実装レベルでのパラメーター名はインターフェースレベルと同じである必要があります。

sonarqubeには、「パラメータ名はベース宣言およびその他の部分的な定義と一致する必要がある」などのルールがあり、これを「非準拠コード」と呼びます。

interface IFoo
{
  void Bar(int i);
}

class Foo : IFoo
{
  void Bar(int z) // Noncompliant, parameter name should be i
  {
  }
}

面白いのは、このドキュメントを参照していないことですinterfacehttps ://wiki.sei.cmu.edu/confluence/display/c/DCL40-C.+Do+not+create+incompatible+declarations+of+the +同じ+関数+または+オブジェクト

私は個人的に次のようなコードが好きです:

public interface IExtractor<TInput, TOutput>{
    TOutput Extract(TInput input);
}

public class CustomerExtractor : IExtractor<Order, Customer>
{
    public Customer Extract(Order order)
    {
        // ...
    }
}

しかし、ツールは私にそれを重大な問題として宣言する次のものを使用することを強制します:

    public Customer Extract(Order input)
    {
        // ...
    }

inputorderこの場合と同じ意味ではありません。

ノイズを取り除くために、

  • DIが含まれていない場合は、この種のクラス(Map、Extract、Combineなど)に静的ユーティリティクラスを使用します。
  • DIが関係している場合は、ヘルパー変数を追加してツールをだまします
    public Customer Extract(Order input)
    {
       var order = input;

       // use order from here on
    }
于 2020-05-18T17:33:39.617 に答える
1

これは、C#の名前付きパラメーター機能によるものだと思います。つまり、デフォルトの順序だけでなく、名前でパラメータを指定できる必要があります。

IActivityDao dao;
dao.GetAllSinceSequence(count: 1, sequence: 2);

もちろん、オブジェクトがインスタンスとしてキャストされている場合、パラメーター名は異なります。

var concreteDao = (ActivityDao) dao;
concreteDao.GetAllSinceSequence(maxRecords: 1, sequence: 2);
于 2012-09-04T23:45:23.657 に答える
1

C#やVBのような多くの言語は、メソッドへの名前付き引数とオプション引数をサポートしています。インターフェイスに引数名がないと、名前付き引数とオプションの引数を使用できません。引数に名前を付けると、読者がインターフェースの意図と機能を理解するのにも役立ちます。

于 2012-09-04T23:48:52.097 に答える