What is the equivalent of a 'friend' keyword in C Sharp?

前端 未结 7 1191
既然无缘
既然无缘 2021-02-18 15:52

What is the equivalent of a \'friend\' keyword in C Sharp?

How do I use the \'internal\' keyword?

I have read that \'internal\' keyword is a replacement for \'fr

7条回答
  •  栀梦
    栀梦 (楼主)
    2021-02-18 16:08

    Here's a weird trick I used for adding behaviour akin to C++'s friend keyword. This only works for nested classes AFAIK.

    1. Create a nested protected or private interface with the variables you'd like to give access to via properties.
    2. Let the nested class inherit this interface and implement it explicitly.
    3. Whenever using an object of this nested class, cast it to the interface and call the respective properties.

    Here's an example from 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
        }
    }
    
    

    I think this only works for nested classes. In case you want to do this with regular classes, you'd need to nest them inside a partial outer class, which should work in theory, and use a protected or private nested interface (or two, if you're inclined) for providing them access to each other's privates... that came out wrong.

提交回复
热议问题