Cシャープの「友達」キーワードに相当するものは何ですか?
「内部」キーワードを使用するにはどうすればよいですか?
'internal'キーワードはC#の 'friend'の代わりになることを読みました。
ソースコードがあるC#プロジェクトでDLLを使用していますが、既存のコードを変更したくありません。クラスを継承しており、継承したクラスを任意に使用できます問題は、親クラスのコードのほとんどに保護されたメソッドがあることです。フレンドを使用すると、これらの保護されたメソッドにアクセスしたり呼び出したりできるようになるのでしょうか。
キーワードアクセス修飾子 internal
を使用して、同じアセンブリ内のコードのみにアクセスできるように型または型メンバーを宣言できます。
InternalsVisibleToAttribute
で定義されたクラスを使用できます System.Rutime.CompilerServices
は、同じアセンブリまたは指定されたアセンブリのみでコードにアクセスできるように型を宣言します。
private
などの他の アクセス修飾子 を使用する場合と同様に、最初のものを使用します。ウィットするには:
internal class MyClass {
...
}
次のように2番目を使用します。
[Assembly:InternalsVisibleTo("MyFriendAssembly", PublicKey="...")]
internal class MyVisibleClass {
...
}
これらはどちらも、C#ではfriend
と同等と見なすことができます。
protected
であるメソッドは、派生クラスですでに使用可能です。
いいえ、「内部」は「友達」と同じではありません(少なくともC++の「友達」)
friendは、このクラスにアクセスできるのは、特定のクラスのONEだけであることを指定しています。
internalは、このクラスがアセンブリの任意のクラスからアクセスできることを指定します。
internal
は、VB.NETのfriend
キーワードと同等のC#です(ご想像のとおり(置き換えではありません))。
使い方は以下の通り
internal void Function() {}
internal Class Classname() {}
internal int myInt;
internal int MyProperty { get; set; }
基本的には、内部としてマークされたクラス/関数/変数/プロパティのアクセシビリティは、それがコンパイルされたアセンブリに対してパブリックであり、他のアセンブリに対してプライベートであるかのように規定するアクセス修飾子です。
これが、C++のfriend
キーワードに類似した動作を追加するために使用した奇妙なトリックです。 これはネストされたクラスAFAIKでのみ機能します。
protected
またはprivate
インターフェースを作成します。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つは、必要に応じて)お互いのプライベートにアクセスできるようにするためです...
サブクラスは、継承したクラスの保護されたメンバーにアクセスできます。
これらの保護されたメンバーへのアクセス権を別のクラスに付与しようとしていますか?
内部は友達と同等です。プロテクトメソッドは、同じクラス内または継承元からのみ使用できます。継承されたメソッドから保護されたメソッドを公開しようとしている場合は、それらをパブリックメソッドでラップできます。