powered by simpleCommunicator - 2.0.55     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Помогите с переводом C++ -> C#
10 сообщений из 10, страница 1 из 1
Помогите с переводом C++ -> C#
    #38876121
Алексей Ку.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый день!

Возникла задача перевести некоторые классы с плюсов на шарп. Я не уверен что всё делаю верно. Если кому не сложно, то прошу глянуть что у меня получается.

Для начала я решил перенести header без реализаций.

Метками //TODO указал для себя места с которыми не до конца всё ясно.

Исходный код на плюсах:

Код: plaintext
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.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
// Сообщения парсера
static const AnsiString S_SetInput = "Входные данные обновлены: \"%s\"";
static const AnsiString S_SetOutput = "Выходные данные обновлены: \"%s\"";
static const AnsiString S_Parse = "Парсер не реализован: %s";
static const AnsiString S_ParserException = "Исключение парсера с сообщением \"%s\"";
static const AnsiString S_PackageDuplicated = "Дубликат посылки в данных: \"%s\"";
static const AnsiString S_PackageCorrupted = "Посылка испорчена: \"%s\"";
static const AnsiString S_PackageNotFound = "Посылка не найдена: \"%s\"";
static const AnsiString S_InsufficientData = "Недостаточно данных: \"%s\"";
static const AnsiString S_GetDataAndIndicators = "Запросить результат взвешивания и состояния индикаторов";
static const AnsiString S_SetNextParser = "Парсер класса %s будет следующим по цепочке";
static const AnsiString S_UnsetNextParser = "Парсер класса %s исключён из цепочки";
static const AnsiString S_NextParser = "Передача управления следующему по цепочке парсеру класса %s";
static const AnsiString S_OddSymbolsDeleted = "Лишние символы в начале входных данных удалены: %d";

// Escape-последовательности и их заменители в тексте, а также другие символы
static const AnsiString S_BEL = "\a";
static const AnsiString S_Bell = "\\a";
static const AnsiString S_BS = "\b";
static const AnsiString S_Backspace = "\\b";
static const AnsiString S_FF = "\f";
static const AnsiString S_Formfeed = "\\f";
static const AnsiString S_LF = "\n";
static const AnsiString S_NewLine = "\\n";
static const AnsiString S_CR = "\r";
static const AnsiString S_CarriageReturn = "\\r";
static const AnsiString S_HT = "\t";
static const AnsiString S_HorizontalTab = "\\t";
static const AnsiString S_VT = "\v";
static const AnsiString S_VerticalTab = "\\v";
static const AnsiString S_Empty = "";
static const AnsiString S_Space = " ";
static const AnsiString S_FullStop = ".";
static const AnsiString S_Comma = ",";
static const AnsiString S_Zero = "0";

// Тип события по добавлении записи в журнал
typedef void __fastcall (__closure *TLogEvent)(System::TObject* Sender, AnsiString Message);

// Класс абстрактного парсера
class TAbstractParser : public System::TObject
{
private:
        TStrings* FDuplicates;
        Boolean FIgnoreDuplicates;
        TAbstractParser* FNextParser;
        TObjectList* FPreviousParsers;
        TNotifyEvent FOnInput;
        TNotifyEvent FOnOutput;
        TLogEvent FOnLog;
protected:
        AnsiString FVersion;
        AnsiString FInput;
        AnsiString FOutput;
        AnsiString FSTX;
        AnsiString FETX;
        Integer FPackageSize;
        Boolean FParseOnlyLast;
        Boolean FIsValid;

        void virtual __fastcall SetInput(AnsiString Value);
        void virtual __fastcall SetOutput(AnsiString Value);
        void virtual __fastcall SetNextParser(TAbstractParser* Value);

        void virtual __fastcall DoInput(void);
        void virtual __fastcall DoOutput(void);
        void virtual __fastcall DoLog(AnsiString Message);
        void virtual __fastcall DoLog(AnsiString Message, const System::TVarRec * Args, const int Args_Size);

        Integer virtual __fastcall Find(AnsiString& AInput);
        Boolean virtual __fastcall Parse(AnsiString APackage);
        void virtual __fastcall RegisterPreviousParser(TAbstractParser* AParser);
        void virtual __fastcall UnregisterPreviousParser(TAbstractParser* AParser);
        static Integer __fastcall CheckCharset(AnsiString S, const AnsiString Charset = "0123456789");

        __property AnsiString STX = { read = FSTX };
        __property AnsiString ETX = { read = FETX };
        __property Integer PackageSize = { read = FPackageSize };
        __property Boolean ParseOnlyLast = { read = FParseOnlyLast };
public:
        virtual __fastcall TAbstractParser(void);
        virtual __fastcall ~TAbstractParser(void);
        static AnsiString __fastcall BufferToStr(AnsiString Buffer);
        __property AnsiString Version = { read = FVersion };
        __property AnsiString Input = { read = FInput, write = SetInput };
        __property AnsiString Output = { read = FOutput, write = SetOutput };
        __property Boolean IgnoreDuplicates = { read = FIgnoreDuplicates, write = FIgnoreDuplicates };
        __property Boolean IsValid = { read = FIsValid };
        __property TAbstractParser* NextParser = { read = FNextParser, write = SetNextParser };
        __property TNotifyEvent OnInput = { read = FOnInput, write = FOnInput };
        __property TNotifyEvent OnOutput = { read = FOnOutput, write = FOnOutput };
        __property TLogEvent OnLog = { read = FOnLog, write = FOnLog };
};





Что вышло на шарпе:

Код: 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.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
 #region constants
        // Сообщения парсера
        const string S_SetInput = "Входные данные обновлены: \"%s\"";
        const string S_SetOutput = "Выходные данные обновлены: \"%s\"";
        const string S_Parse = "Парсер не реализован: %s";
        const string S_ParserException = "Исключение парсера с сообщением \"%s\"";
        const string S_PackageDuplicated = "Дубликат посылки в данных: \"%s\"";
        const string S_PackageCorrupted = "Посылка испорчена: \"%s\"";
        const string S_PackageNotFound = "Посылка не найдена: \"%s\"";
        const string S_InsufficientData = "Недостаточно данных: \"%s\"";
        const string S_GetDataAndIndicators = "Запросить результат взвешивания и состояния индикаторов";
        const string S_SetNextParser = "Парсер класса %s будет следующим по цепочке";
        const string S_UnsetNextParser = "Парсер класса %s исключён из цепочки";
        const string S_NextParser = "Передача управления следующему по цепочке парсеру класса %s";
        const string S_OddSymbolsDeleted = "Лишние символы в начале входных данных удалены: %d";

        // Escape-последовательности и их заменители в тексте, а также другие символы
        const string S_BEL = "\a";
        const string S_Bell = "\\a";
        const string S_BS = "\b";
        const string S_Backspace = "\\b";
        const string S_FF = "\f";
        const string S_Formfeed = "\\f";
        const string S_LF = "\n";
        const string S_NewLine = "\\n";
        const string S_CR = "\r";
        const string S_CarriageReturn = "\\r";
        const string S_HT = "\t";
        const string S_HorizontalTab = "\\t";
        const string S_VT = "\v";
        const string S_VerticalTab = "\\v";
        const string S_Empty = "";
        const string S_Space = " ";
        const string S_FullStop = ".";
        const string S_Comma = ",";
        const string S_Zero = "0";
        #endregion

        #region PRIVATE
        //TStrings* FDuplicates;
        private string[] FDuplicates;
        //Boolean FIgnoreDuplicates;
        private bool FIgnoreDuplicates;
        //TAbstractParser* FNextParser;
        private TAbstractParser FNextParser;
        //TObjectList* FPreviousParsers;
        private object[] FPreviousParsers;
        //TNotifyEvent FOnInput;
        private EventHandler FOnInput;
        //TNotifyEvent FOnOutput;
        private EventHandler FOnOutput;
        //TLogEvent FOnLog;
        //TODO TLogEvent FOnLog; 

        #endregion



        #region PROTECTED
        //AnsiString FVersion;
        protected string FVersion;
        //AnsiString FInput;
        protected string FInput;
        //AnsiString FOutput;
        protected string FOutput;
        //AnsiString FSTX;
        protected string FSTX;
        //AnsiString FETX;
        protected string FETX;
        //Integer FPackageSize;
        protected int FPackageSize;
        //Boolean FParseOnlyLast;
        protected bool FParseOnlyLast;
        //Boolean FIsValid;
        protected bool FIsValid;

        //void virtual __fastcall SetInput(AnsiString Value);
        protected void SetInput(string Value) { }
        //void virtual __fastcall SetOutput(AnsiString Value);
        protected void SetOutput(string Value) { }
        //void virtual __fastcall SetNextParser(TAbstractParser* Value);
        protected void SetNextParser(TAbstractParser Value) { }
        //void virtual __fastcall DoInput(void);
        protected void DoInput() { }
        //void virtual __fastcall DoOutput(void);
        protected void DoOutput() { }
        //void virtual __fastcall DoLog(AnsiString Message);
        protected void DoLog(string Message) { }
        //void virtual __fastcall DoLog(AnsiString Message, const System::TVarRec * Args, const int Args_Size);
        //TODO void virtual __fastcall DoLog(AnsiString Message, const System::TVarRec * Args, const int Args_Size);

        //Integer virtual __fastcall Find(AnsiString& AInput);
        protected int Find(string AInput) { return 0; }

        //Boolean virtual __fastcall Parse(AnsiString APackage);
        protected bool Parse(string APackage) { return false; }

        //void virtual __fastcall RegisterPreviousParser(TAbstractParser* AParser);
        protected void RegisterPreviousParser(TAbstractParser AParser) { }

        //void virtual __fastcall UnregisterPreviousParser(TAbstractParser* AParser);
        protected void UnregisterPreviousParser(TAbstractParser AParser) { }

        //static Integer __fastcall CheckCharset(AnsiString S, const AnsiString Charset = "0123456789");
        protected static int CheckCharset(string S, string Charset = "0123456789") { return 0; }

        //__property AnsiString STX = { read = FSTX };
        string STX { get { return FSTX; } }

        //__property AnsiString ETX = { read = FETX };
        string ETX { get { return FETX; } }

        //__property Integer PackageSize = { read = FPackageSize };
        int PackageSize { get { return FPackageSize; } }

        //__property Boolean ParseOnlyLast = { read = FParseOnlyLast };
        bool ParseOnlyLast { get { return FParseOnlyLast; } }

        #endregion

        #region PUBLIC
        //virtual __fastcall TAbstractParser(void);
        public TAbstractParser() { }

        //virtual __fastcall ~TAbstractParser(void);
        public ~TAbstractParser() { }

        //static AnsiString __fastcall BufferToStr(AnsiString Buffer);
        public string BufferToStr(string Buffer) { return null; }

        //__property AnsiString Version = { read = FVersion };
        public string Version
        {
            get { return Assembly.GetEntryAssembly().GetName().Version.ToString(); }
            //TODO А точно ли Assembly.GetEntryAssembly().GetName().Version.ToString()?
        }

        //__property AnsiString Input = { read = FInput, write = SetInput };
        public string Input
        {
            get { return FInput; }
            set {/*TODO SetInput*/}
        }

        //__property AnsiString Output = { read = FOutput, write = SetOutput };
        public string Output
        {
            get { return FOutput; }
            set {/*TODO SetOutput*/}
        }

        //__property Boolean IgnoreDuplicates = { read = FIgnoreDuplicates, write = FIgnoreDuplicates };
        public bool IgnoreDuplicates
        {
            get { return FIgnoreDuplicates; }
            set { FIgnoreDuplicates = value; }
        }

        //__property Boolean IsValid = { read = FIsValid };
        public bool IsValid
        {
            get { return FIsValid; }
        }

        //__property TAbstractParser* NextParser = { read = FNextParser, write = SetNextParser };
        public TAbstractParser NextParser
        {
            get { return FNextParser; }
            set {/*TODO  SetNextParser*/}
        }

        //__property TNotifyEvent OnInput = { read = FOnInput, write = FOnInput };
        public EventHandler OnInput
        {
            get { return FOnInput; }
            set { FOnInput = value; }
        }

        //__property TNotifyEvent OnOutput = { read = FOnOutput, write = FOnOutput };
        public EventHandler OnOutput
        {
            get { return FOnOutput; }
            set { FOnOutput = value; }
        }

        //__property TLogEvent OnLog = { read = FOnLog, write = FOnLog }; 
        //TODO __property TLogEvent OnLog = { read = FOnLog, write = FOnLog }; 
        #endregion




Выдержка строк, которые вызвали затруднение при переносе:
плюсы:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
private:
        TLogEvent FOnLog;

protected:
        void virtual __fastcall DoLog(AnsiString Message, const System::TVarRec * Args, const int Args_Size);

public:
        __property AnsiString Version = { read = FVersion };
        __property TLogEvent OnLog = { read = FOnLog, write = FOnLog };




шарп:

Код: c#
1.
2.
3.
4.
5.
        //TLogEvent FOnLog;
        //TODO TLogEvent FOnLog; 

        //void virtual __fastcall DoLog(AnsiString Message, const System::TVarRec * Args, const int Args_Size);
        //TODO void virtual __fastcall DoLog(AnsiString Message, const System::TVarRec * Args, const int Args_Size);



//__property AnsiString Version = { read = FVersion };
public string Version
{
get { return Assembly.GetEntryAssembly().GetName().Version.ToString(); }
//TODO А точно ли Assembly.GetEntryAssembly().GetName().Version.ToString()?
}

//__property TLogEvent OnLog = { read = FOnLog, write = FOnLog };
//TODO __property TLogEvent OnLog = { read = FOnLog, write = FOnLog };
...
Рейтинг: 0 / 0
Помогите с переводом C++ -> C#
    #38876124
Алексей Ку.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей Ку.,
"Плюсовая" версия писалась на Borland C++ Builder 6 (это имеет значение?)
Забыл ещё уточнить про этот момент

Правильно ли преобразовал типы?
Плюсы:
__property TNotifyEvent OnInput = { read = FOnInput, write = FOnInput };
__property TNotifyEvent OnOutput = { read = FOnOutput, write = FOnOutput };

Шарп:
private EventHandler FOnInput;
private EventHandler FOnOutput;
...
Рейтинг: 0 / 0
Помогите с переводом C++ -> C#
    #38876171
Алексей Ку.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И ещё вот тут вопрос:
Плюсы:
объявление в хидере
TStrings* FDuplicates;
инициализация в СРР
FDuplicates = new TStringList();

Какой аналог этого дела в шарпе?
...
Рейтинг: 0 / 0
Помогите с переводом C++ -> C#
    #38876179
bazile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей Ку.Правильно ли преобразовал типы?
Плюсы:
__property TNotifyEvent OnInput = { read = FOnInput, write = FOnInput };
__property TNotifyEvent OnOutput = { read = FOnOutput, write = FOnOutput };

Шарп:
private EventHandler FOnInput;
private EventHandler FOnOutput;

По моему нет. Это должно быть событие или свойство где get содержит код из read, a set код из write


Алексей Ку.Плюсы:
объявление в хидере
TStrings* FDuplicates;
инициализация в СРР
FDuplicates = new TStringList();

Какой аналог этого дела в шарпе?
Я бы использовал List<string>
...
Рейтинг: 0 / 0
Помогите с переводом C++ -> C#
    #38876214
Алексей Ку.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bazileАлексей Ку.Правильно ли преобразовал типы?
Плюсы:
__property TNotifyEvent OnInput = { read = FOnInput, write = FOnInput };
__property TNotifyEvent OnOutput = { read = FOnOutput, write = FOnOutput };

Шарп:
private EventHandler FOnInput;
private EventHandler FOnOutput;

По моему нет. Это должно быть событие или свойство где get содержит код из read, a set код из write

Тут я немного ошибся:
Плюсы:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
private:
        TNotifyEvent FOnInput;
        TNotifyEvent FOnOutput;

public:
        __property TNotifyEvent OnInput = { read = FOnInput, write = FOnInput };
        __property TNotifyEvent OnOutput = { read = FOnOutput, write = FOnOutput };


У меня на шарпе:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
        private EventHandler FOnInput;
        private EventHandler FOnOutput;

        public string Input
        {
            get { return FInput; }
            set {/*TODO SetInput*/}
        }
        public string Output
        {
            get { return FOutput; }
            set {/*TODO SetOutput*/}
        }


SetInput/Output ещё пока что не прописал.
Так верно?


авторАлексей Ку.Плюсы:
объявление в хидере
TStrings* FDuplicates;
инициализация в СРР
FDuplicates = new TStringList();

Какой аналог этого дела в шарпе?
Я бы использовал List<string>
Да, я тоже к нему пришёл
...
Рейтинг: 0 / 0
Помогите с переводом C++ -> C#
    #38876245
bazile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей Ку.Так верно?
Верно или нет решать тебе, но я бы написал так:
Код: c#
1.
2.
public event EventHandler OnInput;
public event EventHandler OnOutput;
...
Рейтинг: 0 / 0
Помогите с переводом C++ -> C#
    #38876255
Алексей Ку.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bazileАлексей Ку.Так верно?
Верно или нет решать тебе, но я бы написал так:
Код: c#
1.
2.
public event EventHandler OnInput;
public event EventHandler OnOutput;



А Вы бы не могли пояснить разницу между
public event EventHandler OnInput;
и
private EventHandler FOnInput;
?
...
Рейтинг: 0 / 0
Помогите с переводом C++ -> C#
    #38876329
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей Ку.,

вроде как event ожно добавить в интерфейс, а поле нельзя. А по сути, это делегат и так и сяк
...
Рейтинг: 0 / 0
Помогите с переводом C++ -> C#
    #38876423
bazile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алексей Ку., разница больше семантическая. С полем типа EventHandler можно обращаться так же как с событием event EventHandler, то есть добавить несколько делегатов с помощью += и они будут выполняться. Но мое восприятие будет разным для этих случаев. Видя событие я понимаю что автор класса хотел чтобы на него подписывались. А глядя на делегат в виде поля класса мне будет непонятно что автор хотел этим сказать. Плюс C# себя немного по другому ведет при внешнем доступе к событию или делегату - событие нельзя сгенерировать извне. Поэтому использование event мне кажется более логичным в данном случае.
...
Рейтинг: 0 / 0
Помогите с переводом C++ -> C#
    #38876509
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bazileразница больше семантическая
Разница самая что ни на есть фактическая. Код
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
class A
{
  public EventHandler SomeAction;
}

class B
{
  public event EventHandler SomeOccured;
}


в первом случае транслируется вот в такой незамысловатый IL:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
.class private auto ansi beforefieldinit test.A
    extends [mscorlib]System.Object
{
    .field public class [mscorlib]System.EventHandler SomeAction

    .method public hidebysig specialname rtspecialname instance void .ctor () cil managed 
    {
        IL_0000: ldarg.0
        IL_0001: call instance void [mscorlib]System.Object::.ctor()
        IL_0006: ret
    }
}


и видно, что объявленный делегат - просто обычное поле. Которому, например, можно "в лоб" присвоить null. С объявленным event'ом такой трюк не выйдет, потому как внутри там все несколько более сложно:
Код: 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.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
.class private auto ansi beforefieldinit test.B
    extends [mscorlib]System.Object
{
    .method public hidebysig specialname rtspecialname instance void .ctor () cil managed 
    {
        IL_0000: ldarg.0
        IL_0001: call instance void [mscorlib]System.Object::.ctor()
        IL_0006: ret
    }

    .event [mscorlib]System.EventHandler SomeOccured
    {
        .addon instance void test.B::add_SomeOccured(class [mscorlib]System.EventHandler)
        {
            .locals init (
                [0] class [mscorlib]System.EventHandler V_0,
                [1] class [mscorlib]System.EventHandler V_1,
                [2] class [mscorlib]System.EventHandler V_2
            )

            IL_0000: ldarg.0
            IL_0001: ldfld class [mscorlib]System.EventHandler test.B::SomeOccured
            IL_0006: stloc.0
            .loop
            {
                IL_0007: ldloc.0
                IL_0008: stloc.1
                IL_0009: ldloc.1
                IL_000a: ldarg.1
                IL_000b: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate,  class [mscorlib]System.Delegate)
                IL_0010: castclass [mscorlib]System.EventHandler
                IL_0015: stloc.2
                IL_0016: ldarg.0
                IL_0017: ldflda class [mscorlib]System.EventHandler test.B::SomeOccured
                IL_001c: ldloc.2
                IL_001d: ldloc.1
                IL_001e: call class [mscorlib]System.EventHandler [mscorlib]System.Threading.Interlocked::CompareExchange<class [mscorlib]System.EventHandler>(!!0&,  !!0,  !!0)
                IL_0023: stloc.0
                IL_0024: ldloc.0
                IL_0025: ldloc.1
                IL_0026: bne.un.s IL_0007
            }
            IL_0028: ret
        }
        .removeon instance void test.B::remove_SomeOccured(class [mscorlib]System.EventHandler)
        {
            .locals init (
                [0] class [mscorlib]System.EventHandler V_0,
                [1] class [mscorlib]System.EventHandler V_1,
                [2] class [mscorlib]System.EventHandler V_2
            )

            IL_0000: ldarg.0
            IL_0001: ldfld class [mscorlib]System.EventHandler test.B::SomeOccured
            IL_0006: stloc.0
            .loop
            {
                IL_0007: ldloc.0
                IL_0008: stloc.1
                IL_0009: ldloc.1
                IL_000a: ldarg.1
                IL_000b: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Remove(class [mscorlib]System.Delegate,  class [mscorlib]System.Delegate)
                IL_0010: castclass [mscorlib]System.EventHandler
                IL_0015: stloc.2
                IL_0016: ldarg.0
                IL_0017: ldflda class [mscorlib]System.EventHandler test.B::SomeOccured
                IL_001c: ldloc.2
                IL_001d: ldloc.1
                IL_001e: call class [mscorlib]System.EventHandler [mscorlib]System.Threading.Interlocked::CompareExchange<class [mscorlib]System.EventHandler>(!!0&,  !!0,  !!0)
                IL_0023: stloc.0
                IL_0024: ldloc.0
                IL_0025: ldloc.1
                IL_0026: bne.un.s IL_0007
            }
            IL_0028: ret
        }}
}


Рихтер вышеприведенное под спойлером демонстрировал в виде такого псевдокода:
Код: 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.
// 1. A PRIVATE delegate field that is initialized to null
private EventHandler<NewMailEventArgs> NewMail = null;
// 2. A PUBLIC add_Xxx method (where Xxx is the Event name)
// Allows methods to register interest in the event.
public void add_NewMail(EventHandler<NewMailEventArgs> value)
{
  // The loop and the call to CompareExchange is all just a fancy way
  // of adding a delegate to the event in a thread-safe way
  EventHandler<NewMailEventArgs> prevHandler;
  EventHandler<NewMailEventArgs> newMail = this.NewMail;
  do
  {
    prevHandler = newMail;
    EventHandler<NewMailEventArgs> newHandler =
    (EventHandler<NewMailEventArgs>)Delegate.Combine(prevHandler, value);
    newMail = Interlocked.CompareExchange<EventHandler<NewMailEventArgs>>(
    ref this.NewMail, newHandler, prevHandler);
  } while (newMail != prevHandler);
}
// 3. A PUBLIC remove_Xxx method (where Xxx is the Event name)
// Allows methods to unregister interest in the event.
public void remove_NewMail(EventHandler<NewMailEventArgs> value)
{
  // The loop and the call to CompareExchange is all just a fancy way
  // of removing a delegate from the event in a thread-safe way
  EventHandler<NewMailEventArgs> prevHandler;
  EventHandler<NewMailEventArgs> newMail = this.NewMail;
  do
  {
    prevHandler = newMail;
    EventHandler<NewMailEventArgs> newHandler =
    (EventHandler<NewMailEventArgs>)Delegate.Remove(prevHandler, value);
    newMail = Interlocked.CompareExchange<EventHandler<NewMailEventArgs>>(
    ref this.NewMail, newHandler, prevHandler);
  } while (newMail != prevHandler);
}


т.е. компилятор как минимум обеспечивает потокобезопасную подписку/отписку (The Interlocked Anything Pattern у того же автора).
...
Рейтинг: 0 / 0
10 сообщений из 10, страница 1 из 1
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Помогите с переводом C++ -> C#
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]