C Sharp中的'friend'关键字相当于什么?

时间:2009-01-15 02:58:55

标签: c# friend internal friend-class

C Sharp中“朋友”关键字的等价物是什么?

如何使用'internal'关键字?

我已经读过“内部”关键字是C#中“朋友”的替代品。

我在我的C#项目中使用了一个DLL,我有源代码,但我不想修改现有的代码。我继承了这个类,我可以以任何我想要的方式使用我继承的类。问题是父类中的大多数代码都有受保护的方法。以某种方式使用朋友可以访问或调用这些受保护的方法吗?

7 个答案:

答案 0 :(得分:34)

  1. 您可以使用关键字访问修饰符internal将类型或类型成员声明为只能在同一个程序集中访问代码。

  2. 您可以使用InternalsVisibleToAttribute中定义的System.Rutime.CompilerServices类将类型声明为同一程序集或指定程序集中的代码可访问。

  3. 您在使用private之类的任何其他access modifier时使用第一个。即:

    internal class MyClass {
        ...
    }
    

    您使用第二个如下:

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

    这两个都可以正确地被认为是C#中的friend

    protected的方法已经可用于派生类。

答案 1 :(得分:30)

不,“内部”与“朋友”不一样(至少是C ++'朋友')

friend指定此类只能由ONE,特定类访问 internal指定程序集中的任何类都可以访问此类。

答案 2 :(得分:6)

1)Internal是VB.NET'friend'关键字的C#equivelant,正如您猜测的那样(而不是替换)

2)用法如下

internal void Function() {}
internal Class Classname() {}
internal int myInt;
internal int MyProperty { get; set; }

3)它基本上是一个访问修饰符,规定标记为internal的class / function / vairiable / property的可访问性就好像它是编译成汇编的程序集是公共的,并且对任何其他程序集是私有的

答案 3 :(得分:1)

您的子类将能够访问您继承的类的受保护成员。

您是否希望将这些受保护的成员访问另一个类?

答案 4 :(得分:0)

内部相当于朋友。受保护的方法仅在同一类或继承者中可用。如果您尝试从继承者公开受保护的方法,可以将它们包装在公共方法中。

答案 5 :(得分:0)

这是我用来添加类似于C ++的friend关键字的行为的怪异技巧。 这仅适用于嵌套类AFAIK。

  1. 创建一个嵌套的protectedprivate接口,其中包含您想通过属性访问的变量。
  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
    }
}

我认为这仅适用于嵌套类。如果您想使用常规类执行此操作,则需要将它们嵌套在局部外部类中,该类应该在理论上起作用,并使用protectedprivate嵌套接口(或两个, (如果您愿意)向他们提供访问彼此私人的权限...错了。

答案 6 :(得分:0)

在两个部分类文件中分割一个大类可以达到所需的效果。它不是等效的,但在某些情况下可以使用。