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

前端 未结 7 1192
既然无缘
既然无缘 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:06

    No, "internal" is not the same as "friend" (at least the C++ 'friend')

    friend specifies that this class is only accessible by ONE, particular class.
    internal specifies that this class is accessible by ANY class in the assembly.

    0 讨论(0)
  • 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.

    0 讨论(0)
  • 2021-02-18 16:16

    Internal is the equivalent of friend. A protected method is only available within the same class or from an inheritor. If you're trying to expose protected methods from an inheritor, you can wrap them in public methods.

    0 讨论(0)
  • 2021-02-18 16:16

    Splitting a big class in two partial class-files can achive the desired friend-effect. It is not equivalent, but it works in some cases.

    0 讨论(0)
  • 2021-02-18 16:20
    1. You can use the keyword access modifier internal to declare a type or type member as accessible to code in the same assembly only.

    2. You can use the InternalsVisibleToAttribute class defined in System.Rutime.CompilerServices to declare a type as accessible to code in the same assembly or a specified assembly only.

    You use the first as you use any other access modifier such as private. To wit:

    internal class MyClass {
        ...
    }
    

    You use the second as follows:

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

    Both of these can rightly be considered the equivalent of friend in C#.

    Methods that are protected are already available to derived classes.

    0 讨论(0)
  • 2021-02-18 16:28
    1. internal is the C# equivalent of the VB.NET friend keyword, as you have guessed (as opposed to a replacement)

    2. Usage is as follows

      internal void Function() {}
      internal Class Classname() {}
      internal int myInt;
      internal int MyProperty { get; set; }
      
    3. It, basically, is an access modifier that stipulates that the accessibility of the class / function / variable / property marked as internal is as if it were public to the Assembly it is compiled in, and private to any other assemblies

    0 讨论(0)
提交回复
热议问题