web-dev-qa-db-ja.com

Cシャープの「友達」キーワードに相当するものは何ですか?

Cシャープの「友達」キーワードに相当するものは何ですか?

「内部」キーワードを使用するにはどうすればよいですか?

'internal'キーワードはC#の 'friend'の代わりになることを読みました。

ソースコードがあるC#プロジェクトでDLLを使用していますが、既存のコードを変更したくありません。クラスを継承しており、継承したクラスを任意に使用できます問題は、親クラスのコードのほとんどに保護されたメソッドがあることです。フレンドを使用すると、これらの保護されたメソッドにアクセスしたり呼び出したりできるようになるのでしょうか。

21
xarzu
  1. キーワードアクセス修飾子 internal を使用して、同じアセンブリ内のコードのみにアクセスできるように型または型メンバーを宣言できます。

  2. InternalsVisibleToAttribute で定義されたクラスを使用できます System.Rutime.CompilerServices は、同じアセンブリまたは指定されたアセンブリのみでコードにアクセスできるように型を宣言します。

privateなどの他の アクセス修飾子 を使用する場合と同様に、最初のものを使用します。ウィットするには:

internal class MyClass {
    ...
}

次のように2番目を使用します。

[Assembly:InternalsVisibleTo("MyFriendAssembly", PublicKey="...")]
internal class MyVisibleClass {
    ...
}

これらはどちらも、C#ではfriendと同等と見なすことができます。

protected であるメソッドは、派生クラスですでに使用可能です。

34
jason

いいえ、「内部」は「友達」と同じではありません(少なくともC++の「友達」)

friendは、このクラスにアクセスできるのは、特定のクラスのONEだけであることを指定しています。
internalは、このクラスがアセンブリの任意のクラスからアクセスできることを指定します。

30
Harley2000
  1. internal は、VB.NETのfriendキーワードと同等のC#です(ご想像のとおり(置き換えではありません))。

  2. 使い方は以下の通り

    internal void Function() {}
    internal Class Classname() {}
    internal int myInt;
    internal int MyProperty { get; set; }
    
  3. 基本的には、内部としてマークされたクラス/関数/変数/プロパティのアクセシビリティは、それがコンパイルされたアセンブリに対してパブリックであり、他のアセンブリに対してプライベートであるかのように規定するアクセス修飾子です。

6
johnc

これが、C++のfriendキーワードに類似した動作を追加するために使用した奇妙なトリックです。 これはネストされたクラスAFAIKでのみ機能します。

  1. プロパティを介してアクセスを許可する変数を使用して、ネストされたprotectedまたはprivateインターフェースを作成します。
  2. ネストされたクラスにこのインターフェースを継承させ、それを実装しますexplicitly
  3. このネストされたクラスのオブジェクトを使用するときはいつでも、それをインターフェースにキャストし、それぞれのプロパティを呼び出します。

Unityの例を示します。

using System;
using UnityEngine;
using UnityEngine.Assertions;

namespace TL7.Stats
{
    [CreateAssetMenu(fileName = "Progression", menuName = "TL7/Stats/New Progression", order = 0)]
    public class Progression : ScriptableObject
    {
        // Provides access to private members only to outer class Progression
        protected interface IProgressionClassAccess
        {
            CharacterClass CharacterClass { get; set; }
        }

        [System.Serializable]
        public struct ProgressionClass : IProgressionClassAccess
        {
            [Header("DO NOT EDIT THIS VALUE.")]
            [SerializeField] private CharacterClass characterClass;
            [Tooltip("Levels are 0 indexed.")]
            [SerializeField] float[] healthOverLevels;

            public float[] HealthOverLevels => healthOverLevels;

            CharacterClass IProgressionClassAccess.CharacterClass
            {
                get => characterClass;
                set => characterClass = value;
            }
        }

        static readonly Array characterClasses = Enum.GetValues(typeof(CharacterClass));
        [SerializeField] ProgressionClass[] classes = new ProgressionClass[characterClasses.Length];

        public ProgressionClass this[in CharacterClass index] => classes[(int)index];

        void Awake()
        {
            for (int i = 0; i < classes.Length; ++i)
            {
                // Needs to be cast to obtain access
                (classes[i] as IProgressionClassAccess).CharacterClass = (CharacterClass)characterClasses.GetValue(i);
            }
        }

#if UNITY_EDITOR
        public void AssertCorrectSetup()
        {
            for (int i = 0; i < characterClasses.Length; ++i)
            {
                CharacterClass characterClass = (CharacterClass)characterClasses.GetValue(i);
                Assert.IsTrue(
                    (this[characterClass] as IProgressionClassAccess).CharacterClass == characterClass,
                    $"You messed with the class values in {GetType()} '{name}'. This won't do."
                );
            }
        }
#endif
    }
}

これはネストされたクラスでのみ機能すると思います。通常のクラスでこれを行う場合は、理論的には機能するはずの部分的な外部クラス内にネストし、protectedまたはprivateのネストされたインターフェイスを使用する必要があります(または2つは、必要に応じて)お互いのプライベートにアクセスできるようにするためです...

1
mushi

サブクラスは、継承したクラスの保護されたメンバーにアクセスできます。

これらの保護されたメンバーへのアクセス権を別のクラスに付与しようとしていますか?

1
strager

内部は友達と同等です。プロテクトメソッドは、同じクラス内または継承元からのみ使用できます。継承されたメソッドから保護されたメソッドを公開しようとしている場合は、それらをパブリックメソッドでラップできます。

0
Jon B