Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > .NET для новичков > В С++ - friend, а в С# - что?


Автор: bvn13 13.8.2009, 14:50
А подскажите, пожалуйста. В С++ есть возможность для класса дать доступ к приват-данным другим функциям/классам с помощью конструкции friend. А есть ли аналог такого в C#? Просто хочу в классе иметь одно свойство (переменную типа string) в привате, но для определенных (других) классов дать к ней полный доступ. Классы не наследуются. Как такое написать?



Что-то типа вот такого:

Код


class CL1 {
   private CL2 class2;

   public ИзменитьПриватноеСвойствоКласса2() {
      CL2.ПриватноеСвойство = "ну вот что-то такое";
   }
}

class CL2 {
   private string ПриватноеСвойтсво;
}



Добавлено через 14 минут и 20 секунд
сам нашел. Ссылка: 

http://www.cyberforum.ru/csharp-net/thread26951.html

цитата:

Цитата

Есть, конечно. Ключевое слово internal встречали?
Это и есть аналог friend.

Член класса с модификатором доступа internal доступен для всех классов внутри одной сборки.

Автор: ДобренькийПапаша 13.8.2009, 15:06
В C# есть мощный механизм, который называется свойства))))
Вы сохраняете инкапсуляцию, объявляя поле как private, но получаете к нему доступ через public свойство, например:

Код

class ProcParams
    {
        private string paramName;
        private SqlDbType dbType;
        private int size;
        private Object value;
        private ParameterDirection direction;

        public ProcParams(string parameterName, SqlDbType dbType,
                                                int size, Object value, ParameterDirection direction)
        {
            this.paramName = parameterName;
            this.dbType = dbType;
            this.size = size;
            this.value = value;
            this.direction = direction;
        }

        public string ParamName
        {
            get { return paramName; }

        }

        public SqlDbType DbType
        {
            get { return dbType; }
        }

        public int Size
        {
            get { return size; }
        }

        public object Value
        {
            get { return value; }
        }

        public ParameterDirection Direction
        {
            get { return direction; }
        }
    }




Теперь к полям класса можно обратиться так:
Код

ProcParams ex=new ProcParams(//передаю всё что надо в конструктор)
{
   string paramName = ex.ParamName; //через свойство обращаюсь к private полю
}

кроме get (если задн только get вы сможете только читать), можно ещё добавить set (на запись).

Вобщем гуглите свойства C#.NET

Автор: azesmcar 13.8.2009, 15:20
Цитата(bvn13 @  13.8.2009,  14:50 Найти цитируемый пост)

Есть, конечно. Ключевое слово internal встречали?
Это и есть аналог friend.

Член класса с модификатором доступа internal доступен для всех классов внутри одной сборки.

И причем тут вообще friend?

Автор: bvn13 13.8.2009, 15:38
Цитата(ДобренькийПапаша @ 13.8.2009,  15:06)
В C# есть мощный механизм, который называется свойства))))
Вы сохраняете инкапсуляцию, объявляя поле как private, но получаете к нему доступ через public свойство, например:

Код

...



Теперь к полям класса можно обратиться так:
Код

...
   string paramName = ex.ParamName; //через свойство обращаюсь к private полю
...

кроме get (если задн только get вы сможете только читать), можно ещё добавить set (на запись).

Вобщем гуглите свойства C#.NET

Да, об этом я знаю. Но когда я объявляю эти get и set, то эти свойства открываются для всех участков кода, где подключен namespace. А мне нужно только для определенных классов дать возможность работать с этими свойствами. Такое возможно?

Добавлено через 1 минуту и 4 секунды
Цитата(azesmcar @ 13.8.2009,  15:20)
Цитата(bvn13 @  13.8.2009,  14:50 Найти цитируемый пост)

Есть, конечно. Ключевое слово internal встречали?
Это и есть аналог friend.

Член класса с модификатором доступа internal доступен для всех классов внутри одной сборки.

И причем тут вообще friend?

эм...... поясните, пожалуйста.  smile 

Автор: azesmcar 13.8.2009, 15:43
Цитата(bvn13 @  13.8.2009,  15:38 Найти цитируемый пост)
эм...... поясните, пожалуйста.  smile  

friend - разрешает доступ функции/классу к приватным членам другого класса.
internal - Член класса с модификатором доступа internal доступен для всех классов внутри одной сборки.

friend - разрешает доступ, internal - спецификатор доступа...не вижу ничего общего между ними.

Автор: bvn13 13.8.2009, 15:49
Цитата(azesmcar @ 13.8.2009,  15:43)
Цитата(bvn13 @  13.8.2009,  15:38 Найти цитируемый пост)
эм...... поясните, пожалуйста.  smile  

friend - разрешает доступ функции/классу к приватным членам другого класса.
internal - Член класса с модификатором доступа internal доступен для всех классов внутри одной сборки.

friend - разрешает доступ, internal - спецификатор доступа...не вижу ничего общего между ними.

а что значит "доступен для всех классов внутри одной сборки"? Имеется в виду один namespace? Или один проект? или что?

Автор: azesmcar 13.8.2009, 15:52
Цитата(bvn13 @  13.8.2009,  15:49 Найти цитируемый пост)
а что значит "доступен для всех классов внутри одной сборки"? Имеется в виду один namespace? Или один проект? или что? 

http://en.wikipedia.org/wiki/.NET_assembly

Автор: bvn13 13.8.2009, 15:54
Цитата(ДобренькийПапаша @  13.8.2009,  15:06 Найти цитируемый пост)
В C# есть мощный механизм, который называется свойства))))



Может, я не понятно написал.... Попробую пояснить. Мне надо, чтобы одно конкретное свойство класса А было доступно (для записи и чтения) только из методов класса В, а из других мест - только для чтения. Так возможно сделать?

Автор: diadiavova 13.8.2009, 17:26
Цитата(bvn13 @  13.8.2009,  16:54 Найти цитируемый пост)
Мне надо, чтобы одно конкретное свойство класса А было доступно (для записи и чтения) только из методов класса В, а из других мест - только для чтения. Так возможно сделать?

Если речь об одном свойстве, то - нет. Можно сделать так, чтобы все члены класса А были видны их В, для этого В надо вложить в А
Код

    public class A
    {
        private int anyField=3;
        public class B
        {
            public int GetAnyFieldValue(A aObj)
            {
                return aObj.anyField;
            }
        }
    }


И теперь код
Код

            var aaa = new A();
            var bbb = new A.B();
            MessageBox.Show(bbb.GetAnyFieldValue(aaa).ToString());


Выведет значение приватного поля класса А.

Автор: ДобренькийПапаша 13.8.2009, 17:35
Уважаемый bvn13, а зачем вы себе так мозг канифолите может скажете? Зачем вам ТАКАЯ инкапсуляция, что вы там такое скрываете?

Автор: Skynin 13.8.2009, 19:51
Аналога в C# нет. (тот кто написал "internal Это и есть аналог friend". просто не в курсе что такое friend в C++ или internal в C#)
Как и многих других вещей из С++. навскидку - const методов.

Вобщем рекомендую изучать С# отдельно, не оглядываясь на С++, потому что у С++ куда больше синтаксических наворотов и возможностей. А если еще и вспомнить про указатели... "Забудьте" С++ быстрее получится изучить C#

Автор: bvn13 13.8.2009, 20:32
Цитата(ДобренькийПапаша @ 13.8.2009,  17:35)
Уважаемый bvn13, а зачем вы себе так мозг канифолите может скажете? Зачем вам ТАКАЯ инкапсуляция, что вы там такое скрываете?

Зачем? Да это очень удобно.

Есть у меня два класса. Один может быть использован независимо от второго (Это и предполагается). А во втором есть переменная с типом первого класса. Но есть в первом классе переменная Идентификатор, которая должна быть в режиме только для чтения. Везде. За исключением второго класса, откуда она устанавливается, предварительно найденная в базе данных. Как на С++ такое делать знаю, а вот как на С# - нет...

Добавлено через 2 минуты и 38 секунд
Цитата(Skynin @  13.8.2009,  19:51 Найти цитируемый пост)
"Забудьте" С++ быстрее получится изучить C#


Эх, забыть... Это очень интересная и полезная вещь в С++... smile Как ее забыть?

Вот мне интересно, неужели в Шарпее вообще невозможно дать доступ к приватной части класса для "узкого круга" процедур?

Автор: azesmcar 13.8.2009, 20:36
bvn13

Дружба - эта самое сильное взаимоотношение классов (ниже по ступеньке идет наследование), очень желательно ее избегать, настолько желательно, что микрософт решила убрать дружественные функции и классы из C#.

Автор: bvn13 13.8.2009, 20:36
Цитата(Skynin @  13.8.2009,  19:51 Найти цитируемый пост)
тот кто написал "internal Это и есть аналог friend"


Уважаемый, я вот уже несколько часов в поисках по интернету... не могу найти, что же значит это "Член класса с модификатором доступа internal доступен для всех классов внутри одной сборки". Не могли бы Вы пояснить, мне несведующему?

Добавлено через 1 минуту и 18 секунд
Цитата(ДобренькийПапаша @  13.8.2009,  17:35 Найти цитируемый пост)
что вы там такое скрываете? 


Объекты базы данных. smile

Автор: azesmcar 13.8.2009, 20:39
Цитата(bvn13 @  13.8.2009,  20:36 Найти цитируемый пост)
Уважаемый, я вот уже несколько часов в поисках по интернету... не могу найти, что же значит это "Член класса с модификатором доступа internal доступен для всех классов внутри одной сборки". Не могли бы Вы пояснить, мне несведующему? 

Ты же сам писал.

Цитата(bvn13 @  13.8.2009,  14:50 Найти цитируемый пост)
Член класса с модификатором доступа internal доступен для всех классов внутри одной сборки.

а что такое сборка - я ответил ссылкой, ты ведь не лекции по C# здесь ожидаешь увидеть?

Вот, немного процитирую
Цитата

The internal keyword is an access modifier for types and type members. Internal types or members are accessible only within files in the same assembly, as in this example:

http://msdn.microsoft.com/en-us/library/7c5ka91b%28VS.80%29.aspx

что такое сборка (assembly)
Цитата

An assembly is a fundamental building block of any .NET Framework application. For example, when you build a simple C# application, Visual Studio creates an assembly in the form of a single portable executable (PE) file, specifically an EXE or DLL.

http://msdn.microsoft.com/en-us/library/ms173099%28VS.80%29.aspx

Например, ты можешь написать DLL, в классах этой DLL использовать спецификатор доступа internal, он будет доступен всем методам в DLL, но пользователь библиотеки не будет иметь доступ к ней. Есть еще protected internal, почитай в MSDN.

Автор: Skynin 13.8.2009, 21:12
Цитата

А во втором есть переменная с типом первого класса. Но есть в первом классе переменная Идентификатор, которая должна быть в режиме только для чтения. Везде. За исключением второго класса, откуда она устанавливается, предварительно найденная в базе данных. Как на С++ такое делать знаю, а вот как на С# - нет...
...
Вот мне интересно, неужели в Шарпее вообще невозможно дать доступ к приватной части класса для "узкого круга" процедур? 

Можно, только руками, не на уровне синтаксиса:

Код


    public class ClassA
    {
        public int anyF {get; private set;}
        public void setAnyF(object sender, int newVal) {
            if (sender is ClassB) anyF = newVal;
            
            throw new Exception(); // чтобы отловить неправильное присваивание. Или закомментировать если не нужно
        }
    }
    
    public class ClassB {
...
        ClassA clA;
...        
        clA.setAnyF(this,12);
...
    }


Цитата

Эх, забыть... Это очень интересная и полезная вещь в С++...

Малополезная вещь при грамотном проектировании.
Решение "в лоб" - выше.

Автор: PashaPash 13.8.2009, 21:34
Skynin, решение влоб ломается вот так
Код

clA.setAnyF(new ClassB(), 12);

Да и хочется же проверки на уровне синтаксиса. smile

bvn13, вообще сама идея выставлять переменную из другого класса - это как-то не комильфо. Вариант - интерфейс с read only проперти. Что-то типа
Код

class CL1
{
    private CL2 class2 = new CL2();

    public void ChangeProperty()
    {
        this.class2.SomeProperty = "ну вот что-то такое";
    }

    public ICL2 Class2Instance
    {
        get
        {
            return this.class2;
        }
    }
}

interface ICL2
{
    string SomeProperty { get; }
}

class CL2 : ICL2
{
    public string SomeProperty { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        CL1 c1 = new CL1();
        c1.ChangeProperty();
        c1.Class2Instance.SomeProperty = ""; // compilation error
    }
}

Автор: nerezus 13.8.2009, 22:13
Цитата

В С++ - friend, а в С# - что? аналог friend в C#
 А в C# отсутствие костылей и знание ООП.

Автор: Bestoloch 14.8.2009, 10:20
На сколько я понимаю абстрагирование слоев это best practice.
В данном случае есть слой работы с базой данных, в работу которого должен вмешаться класс из другого слоя, зачем?

Автор: Skynin 14.8.2009, 10:28
Цитата

решение влоб ломается вот таккод C#

В C# почти все ломается рефлексией. Так что теперь, и не жить?

Задача то - избавиться от непреднамеренно некорректного использования метода присваивания.
А не защита от "хакера".

Если же нужно чтобы только один объект класса мог присвоить, ну так и сделать его синглтоном, и упрятать конструктор без параметров.

Но если быть параноиком, то обсуждение этого плевого вопроса потянет не на одну страницу  smile 

Цитата

Да и хочется же проверки на уровне синтаксиса.


тогда, проверка во время компиляции
Код

public void setAnyF(ClassB sender, int newVal) {
public void setAnyF(ClassC sender, int newVal) {
public void setAnyF(ClassD sender, int newVal) {


где ClassB, ClassC, ClassD - дружественные к ClassA


Автор: PashaPash 14.8.2009, 13:03
Цитата(Skynin @  14.8.2009,  10:28 Найти цитируемый пост)
В C# почти все ломается рефлексией. Так что теперь, и не жить?

Задача то - избавиться от непреднамеренно некорректного использования метода присваивания.
А не защита от "хакера".

IMHO, Защита на уровне синтаксиса не должна ломаться на уровне синтаксиса. Защита на уровне кода не должна ломаться вписыванием не-рефлекш кода. Даже если это защита от дурака, а не от хакера. Любой дурак при попытке вызвать метод неоттуда впишет new ClassB, тупо проверить, а вдруг заработает -  и ведь заработает smile

Ну и в целом система с sender напоминает "скажи пароль - пароль - проходи" smile

Цитата(Skynin @  14.8.2009,  10:28 Найти цитируемый пост)

Задача то - избавиться от непреднамеренно некорректного использования метода присваивания.

Задача - избавится от непреднамеренно некорректного использования метода присваивания без дополнительных телодвижений со стороны используещего. sender - это уже ограничение - нельзя вызвать из статического класса/метода. И повышение coupling - в случае friend или интерфейса реализация ничего не знает о классе-пользователе, в случае sender - знает более чем достаточно. и даже может вызвать в нем что-нибудь - снаружи ж не видно. Для таких случаев есть Interface-Segregation Principle.


Автор: ДобренькийПапаша 14.8.2009, 14:22
Цитата

Ну и в целом система с sender напоминает "скажи пароль - пароль - проходи" 


Так и не проще ли воспользоваться свойствами?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)