Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.92/100: Рейтинг темы: голосов - 100, средняя оценка - 4.92
Технофашист
229 / 217 / 11
Регистрация: 11.03.2009
Сообщений: 887

Дружественные функции

21.03.2009, 14:06. Показов 18919. Ответов 11
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Я так понимаю, что в С# нет такого. Но а существуют ли какие-либо альтернативы?
Нужно чтоб к приватным полям одного класса был доступ только у двух других. Причём даже у самого этого класса не будет методов доступа к своим полям.
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
21.03.2009, 14:06
Ответы с готовыми решениями:

Дружественные числа, через файлы
Здравствуйте, требуется помощь) вот задачка: В файл нужно ввести 2-ва числа и программа должна проверить эти числа и если они являются...

Множественное наследование и дружественные классы
Нуждаюсь в помощи. Базовые классы: Птица (крылья, скорость), Лошадь (цвет, кличка). Класс-наследник: Пегас. Дружественность: класс...

Дружественные числа
Два натуральных числа называют дружественными, если каждое из них равно сумме всех делителей другого, кроме самого этого числа. Найти все...

11
 Аватар для ostgals
886 / 681 / 101
Регистрация: 23.01.2009
Сообщений: 1,582
21.03.2009, 14:22
Есть, конечно. Ключевое слово internal встречали?
Это и есть аналог friend.

Член класса с модификатором доступа internal доступен для всех классов внутри одной сборки.
1
Комбайнёр
 Аватар для MAcK
1606 / 704 / 77
Регистрация: 27.05.2008
Сообщений: 2,535
21.03.2009, 14:25
internal
1
 Аватар для Enifan
1848 / 1190 / 501
Регистрация: 14.10.2018
Сообщений: 3,211
09.02.2019, 14:51
а в чем взаимосвязь между internal и дружественных функций ?

лично я на своем примере не могу понять как мне решить данную задачу

1-ый класс
C#
1
2
3
4
5
6
7
8
9
10
class Test
{
    Node nodes = new Nodes();
 
    void Foo()
    {
        // Здесь нужно чтобы текущий класс мог менять значения в объектах класса Node
        // И это может сделать только он, другие классы смогут использовать Node.x только для чтения
    }
}
2-ой класс
C#
1
2
3
4
5
6
class Node
{
    int x { get; private set; }
 
    public Node() { x = 0;}
}
0
Эксперт .NET
 Аватар для Casper-SC
4434 / 2094 / 404
Регистрация: 27.03.2010
Сообщений: 5,657
Записей в блоге: 1
09.02.2019, 15:46
Enifan, твои примеры в принципе не компилируются. То что ты показал это свойство, а не поле, но так как свойство по умолчанию private, то private set тут не нужен.

Добавлено через 39 секунд
Поля делать открытыми разумно, только если это readonly поля, иначе нужно использовать свойства.

Добавлено через 9 минут
Если тебе нужно писать тесты, то тестовые фреймворки умеют все эти дела делать без всяких friend классов.

Добавлено через 2 минуты
internal тебе поможет, если разместить твои классы в отдельной сборке, внутри которой можно будет менять значение X кем угодно, а сборках, которые ссылаются на эту сборку с классом Node не будет доступа на запись в свойство. В таком случае такой код будет работать:

Сборка
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    public class Node
    {
        public int X { get; internal set; }
 
        public Node()
        {
            X = 0;
        }
    }
 
    class Test
    {
        Node nodes = new Node();
 
        void Foo()
        {
            nodes.X = 0;
        }
    }
Программа, ссылающаяся на сборку
C#
1
2
3
4
5
6
7
8
    class Program
    {
        static void Main(string[] args)
        {
            Node nodes = new Node();
            nodes.X = 0; // Ошибка! 
        }
    }
Добавлено через 10 минут
Или такой вариант. Наследуемся от абстрактного класса классами, которые тестируют. Кем не нужно, тем не наследуемся:

Сборка
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
namespace ClassLibrary1
{
    public abstract class NodeTesterBase
    {
        private readonly Node _node;
 
        protected NodeTesterBase(Node node)
        {
            _node = node;
        }
 
        protected void SetX(int value)
        {
            _node.X = value;
        }
    }
 
    public class Node
    {
        public int X { get; internal set; }
 
        public Node()
        {
            X = 0;
        }
    }
}
Программа
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
using System;
using ClassLibrary1;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            Node nodes = new Node();
            Test tester = new Test(nodes);
            tester.RunTest1(50);
            Console.WriteLine(nodes.X);
 
            Console.ReadKey();
        }
    }
 
    class Test : NodeTesterBase
    {
        public Test(Node node)
            : base(node)
        {
        }
 
        public void RunTest1(int value)
        {
            SetX(value);
        }
    }
}
Добавлено через 12 минут
#######################

Если всё-таки поле, то:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
using System;
 
namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            Node nodes = new Node();
            Test tester = new Test(nodes);
            tester.RunTest1(50);
            Console.WriteLine(tester.DisplayResults());
 
            // nodes.X = 9; // ОШИБКА!
 
            Console.ReadKey();
        }
    }
 
    class Test
    {
        private readonly NodeWrapper _node;
 
        public Test(Node node)
        {
            _node = new NodeWrapper(node);
        }
 
        public void RunTest1(int value)
        {
            _node.X = value;
        }
 
        public string DisplayResults()
        {
            return $"X = {_node.X}";
        }
    }
 
    public class NodeWrapper
    {
        private readonly Node _node;
 
        public NodeWrapper(Node node)
        {
            _node = node;
        }
 
        public int X
        {
            get { return _node._x; }
            set { _node._x = value; }
        }
    }
 
    public class Node
    {
        protected internal int _x;
 
        public Node()
        {
            _x = 0;
        }
    }
}
1
 Аватар для Enifan
1848 / 1190 / 501
Регистрация: 14.10.2018
Сообщений: 3,211
09.02.2019, 17:28
Цитата Сообщение от Casper-SC Посмотреть сообщение
твои примеры в принципе не компилируются
да согласен, я пропустил модификатор public к свойству Node.X

насчет internal понял что он имеет смысл только в сборках (с этим я еще не сталкивался, разные сборки делать еще не приходилось, да и не знаю как)

за примеры спасибо, более любопытный был последний. жаль что для одного свойства придется прописывать 30+ строк кода. у меня по логике таких свойств штук 5, и на каждое свойство столько кода - как по мне это не шутки...

все таки жаль что модификатора friend не существует, с ним либо кода меньше (причем значительно) либо сборку делать не надо
0
Эксперт .NET
 Аватар для Casper-SC
4434 / 2094 / 404
Регистрация: 27.03.2010
Сообщений: 5,657
Записей в блоге: 1
09.02.2019, 17:44
Цитата Сообщение от Enifan Посмотреть сообщение
насчет internal понял что он имеет смысл только в сборках (с этим я еще не сталкивался, разные сборки делать еще не приходилось, да и не знаю как)
Создаёшь проект (твоя программа).
Создаёшь библиотеку добавив её в решение (Solution). На этом этапе в решении у тебя два проекта.
Добавляешь ссылку на библиотеку из своего приложения.

Добавлено через 2 минуты
Цитата Сообщение от Enifan Посмотреть сообщение
жаль что для одного свойства придется прописывать 30+ строк кода. у меня по логике таких свойств штук 5, и на каждое свойство столько кода - как по мне это не шутки...
Для каждого свойства или поля в отдельности нужно дописывать 5 строк кода.

Добавлено через 1 минуту
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 
    public class NodeWrapper
    {
        private readonly Node _node;
 
        public NodeWrapper(Node node)
        {
            _node = node;
        }
 
        public int X
        {
            get { return _node._x; }
            set { _node._x = value; }
        }
 
        public int Y
        {
            get { return _node._y; }
            set { _node._y = value; }
        }
 
        public int Z
        {
            get { return _node._z; }
            set { _node._z = value; }
        }
    }
Добавлено через 1 минуту
Вообще в таких случаях нужно понимать твою задачу, все эти обсуждения имеют конечно смысл, но от них иногда мало толку, так как ты можешь пытаться решить задачу вообще неверным способом, а знать об этом не будешь. В чём конкретно твоя задача?

Добавлено через 1 минуту
Цитата Сообщение от Enifan Посмотреть сообщение
все таки жаль что модификатора friend не существует, с ним либо кода меньше (причем значительно) либо сборку делать не надо
Я думаю, он не существует совсем не просто так. Опытные люди поняли, что не стоит добавлять такое в C# и 100% правильно сделали.

Добавлено через 36 секунд
Как и нет в C# множественного наследования, кому-то это тоже может показаться минусом.

Добавлено через 3 минуты
Кстати, для возможности присвоения значения можно использовать не свойства, а методы и писать их хоть в одну строку.
C#
1
        public SetX(int value) { _node._x = value; }
Добавлено через 59 секунд
Правда я считаю, что все эти ухищрения с записью лишь бы было в одну строку излишни. Код должен быть читабельным, а не сплошным месивом из длинных строк.
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,574
09.02.2019, 18:01
Цитата Сообщение от Casper-SC Посмотреть сообщение
Кстати, для возможности присвоения значения можно использовать не свойства, а методы и писать их хоть в одну строку.
Можно и без методов
C#
1
public int X { get => _node._x; set => _node._x = value; }
0
Эксперт .NET
 Аватар для Casper-SC
4434 / 2094 / 404
Регистрация: 27.03.2010
Сообщений: 5,657
Записей в блоге: 1
09.02.2019, 18:21
Цитата Сообщение от Someone007 Посмотреть сообщение
Можно и без методов
Это как раз тот вариант, который мне лично не нравится. Делать свойство с одним сеттером, как-то не очень идея, я и предложил метод. Да и вообще писать в одну строку тоже идея так себе. Я никогда не понимал такой "экономии". Лучше писать понятный, читаемый код; от которого не рябит в глазах.
0
 Аватар для Enifan
1848 / 1190 / 501
Регистрация: 14.10.2018
Сообщений: 3,211
09.02.2019, 19:53
лично мне хочется сделать красивую менюшку в консоли (про WinForm я в курсе, с ним уже работал), пока в WinForm не лезу, хочу до конца разобраться со всеми возможностями c# (по шилдту), почитал новую тему - применил на практике, так и обучаюсь (в данном случаи реально понимаю где может пригодиться та или иная возможность, которую разработчики ввели в c#). а в целом делаю морской бой (на c++ уже делал с корявым кодом и заставлял бота играть против бота ))). с логикой проблем нет, а вот синтаксис языка и его тонкости подучить бы надо, на них обычно много времени и трачу.

по поводу текущей задачи - меню -> стрелочная навигация + кольцевой двусвязный список + немного издевательства над консолью.

координаты начала текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
    class Coordinate
    {
        // временно сделал public
        public int X { get; set; }
        public int Y { get; set; }
 
        public Coordinate(int x, int y)
        {
            X = x;
            Y = y;
        }
    }
сам текст, каждому тексту в меню принадлежат свои координаты
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Texts
    {
        readonly string Text;
        public readonly Coordinate coordinate;
 
        public Texts(string text, int x, int y)
        {
            Text = text;
            coordinate = new Coordinate(x, y);
        }
 
        public void PrintText()
        {
            Console.SetCursorPosition(coordinate.X, coordinate.Y);
            Console.Write(Text);
        }
    }
Данные, которые хранятся в кольцевом двусвязном списке
C#
1
2
3
4
5
6
7
8
9
10
11
12
class DataMenu
    {
        public readonly Texts text;
        //public readonly int number;
        //public readonly SymbolArrow symbol;
        //public readonly Deleg deleg;
 
        public DataMenu(string str, int number, int count, Deleg deleg)
        {
            // банальный конструктор
        }
    }
// часть основного класса Меню
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Menu
{
    // Кольцевой двусвязный список (работает как и должен)
    CircleDoubleList<DataMenu> lst = new CircleDoubleList<DataMenu>();
    lst.Add(*/   */);
    lst.Add(*/   */);
 
    void SetCoordinates()
        {
            // далее циклом по имеющемуся списку расставляем координаты, где должен начинаться текст от меню
            // логика простая, вычеты по текущему размеру консоли помещаем текст в центр
            // суть в том, чтобы только этот метод мог редактировать в классе Coordinate методы X и Y (для этого и хотелось бы дружественную функцию)
            lst.Current().text.coordinate.X = (Console.WindowWidth - lst.Current().text.ToString().Length) / 2;
        }
}
0
Эксперт .NETАвтор FAQ
 Аватар для Storm23
10427 / 5157 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
10.02.2019, 09:34
Цитата Сообщение от Enifan Посмотреть сообщение
все таки жаль что модификатора friend не существует
Лично я считаю friend методы довольно бессмысленными.
Но если очень хочется, то можно сделать это через ближайший аналог - приватные интерфейсы.

Это делается так:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
    public class Program
    {
        static void Main(string[] args)
        {
            var node = new Node();
            node.X = 23; //do not allow !!!
            ((INodePrivate)node).X = 23;//allow !!!
        }
    }
    
    internal interface INodePrivate
    {
        int X { set; }
    }
 
    class Node : INodePrivate
    {
        private int x;
 
        public int X
        {
            get { return x; }
        }
 
        int INodePrivate.X
        {
            set { x = value; }
        }
 
        public Node()
        {
            X = 0;//do not allow !!!
        } 
    }
Свойство X будет доступно на запись только если явно привести объект Node к интерфейсу INodePrivate. В противном случае - X только для чтения.

Члены приватного интерфейса нельзя вызвать без приведения к этому интерфейсу, также они не появляются в списке подсказок в IntelliSense. Если вы не знаете о существовании интерфейса INodePrivate то вы никогда и не догадаетесь, что у объекта есть такие методы/свойства.
1
 Аватар для Enifan
1848 / 1190 / 501
Регистрация: 14.10.2018
Сообщений: 3,211
11.02.2019, 20:48
Всем спасибо за ответы, не думал что только способов решения можно сделать с помощью логики, хотя по сути все обертки. Сделал свои поля public и перестал заморачиваться над решением своей задачи.

А что насчет дружественных функций - нет так нет, да и фиг с ними )) Найдем другие пути решения задач.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
11.02.2019, 20:48
Помогаю со студенческими работами здесь

Дружественные функции. Наследование. Перегрузка функции
Здравствуйте, у меня проблема Не знаю куда Вставить имеющийся код(В какую строчку или строчки кода). Первый код это было 1 задание, 2-ой...

Дружественные функции
Создать класс «студент» (его фамилия, имя, год рождения и год поступления). Написать: а) член-функцию печати информации о студенте; ...

дружественные функции
Имеется следующий код, содержащий дружественную функцию: mt.h #ifndef MT_H_ #define MT_H_ class Time { private: int...

Дружественные функции С++
Здравствуйте, помогите пожалуйста решить задачку с помощью дружественных функций: Считайте текст и выведите на экран исходный текст, а...

Дружественные функции
С дружественными классами разобрался, спасибо. А теперь ф-ции. Киньте пожалуста простой пример: класс(несколько полей), обьект описаный в...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Новые блоги и статьи
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru