Подтвердить что ты не робот

Что эквивалентно ключевому слову 'friend' в C Sharp?

Что эквивалентно ключевому слову 'friend' в C Sharp?

Как использовать ключевое слово 'internal'?

Я прочитал, что ключевое слово "internal" является заменой "друга" на С#.

Я использую DLL в своем проекте С#, для которого у меня есть исходный код, и все же я не хочу изменять существующий код. Я унаследовал класс, и я могу использовать свой унаследованный класс любым способом. Проблема в том, что большая часть кода в родительском классе имеет защищенные методы. Будет ли использование друга каким-то образом позволить получить доступ или вызвать эти защищенные методы?

4b9b3361

Ответ 1

  • Вы можете использовать модификатор доступа по ключевым словам internal, чтобы объявить член типа или типа доступным для кода в той же сборке только.

  • Вы можете использовать класс InternalsVisibleToAttribute, определенный в System.Rutime.CompilerServices, чтобы объявить тип доступным для кода только в той же сборке или только в указанной сборке.

Вы используете первый, используя другой модификатор доступа, например private. К остроумию:

internal class MyClass {
    ...
}

Вы используете второй вариант следующим образом:

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

Оба они по праву могут считаться эквивалентом friend в С#.

Способы protected уже доступны для производных классов.

Ответ 2

Нет, "внутренний" - это не то же самое, что "друг" (по крайней мере, С++ "друг" )

friend указывает, что этот класс доступен только для ONE, определенного класса.
internal указывает, что этот класс доступен ЛЮБОЙ класс в сборке.

Ответ 3

  1. internal - это эквивалент С# ключевого слова VB.NET friend, как вы уже догадались (в отличие от замены)

  2. Использование выглядит следующим образом:

    internal void Function() {}
    internal Class Classname() {}
    internal int myInt;
    internal int MyProperty { get; set; }
    
  3. По сути, это модификатор доступа, который предусматривает, что доступность класса/функции/переменной/свойства, помеченного как внутренняя, как если бы он был общедоступным для сборки, в которой он компилируется, и частной для любых других сборок

Ответ 4

Ваш подкласс сможет получить доступ к защищенным членам класса, который вы наследуете.

Вы хотите предоставить доступ к этим защищенным членам в другой класс?

Ответ 5

Вот странный трюк, который я использовал для добавления поведения, похожего на ключевое слово friend C++. Это работает только для вложенных классов AFAIK.

  1. Создайте вложенный protected или private интерфейс с переменными, к которым вы хотите предоставить доступ через свойства.
  2. Пусть вложенный класс наследует этот интерфейс и реализует его явно.
  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 вложенный интерфейс (или два, если вы склонны) для обеспечения они имеют доступ друг к другу, что не так.

Ответ 6

Внутренний - это эквивалент друга. Защищенный метод доступен только в том же классе или у наследника. Если вы пытаетесь открыть защищенные методы у наследника, вы можете обернуть их в общедоступные методы.