2
|
1 # ChristieのC#への書き換えログ
|
|
2
|
|
3 ## メソッド等の置換一覧
|
|
4 java ConcurrentHashMap<> → C# ConcurrentDictionary<>
|
|
5 java map<> → C# Dictionary<>
|
|
6 java getClass() → C# GetType()
|
|
7 java getGenericSuperclass() → C# type.BaseType 補足あり
|
|
8 java ClassCastException → C# InvalidCastException
|
|
9 java ByteBuffer → C# MemoryStream
|
|
10 ```
|
|
11 java
|
|
12 T data = null;
|
|
13 Class<T> clazz = null;
|
|
14 byte[] messsagePack = null;
|
|
15 MessagePack packer = new MessagePack();
|
|
16 // write read
|
|
17 messagePack = packer.write(data);
|
|
18 packer.read(messagePack, clazz);
|
|
19
|
0
|
20
|
2
|
21 C#
|
|
22 T data;
|
|
23 Type clazz = null;
|
|
24 byte[] messagePack = null;
|
|
25 // write read
|
|
26 messagePack = MessagePackSerializer.Serialize(data);
|
|
27 MessagePackSerializer.Deserialize<T>(messagePack);
|
|
28 ```
|
|
29 java TreeMap<> → C# SortedDictionary<>
|
|
30 java HashMap<> → C# Dictionary<>
|
|
31 java Class clazz → C# Type clazz
|
15
|
32 java LinkedBlockingQueue<> → C# ~~ConcurrentQueue<>~~ → BlockingCollection<>
|
2
|
33 java socket.getInetAddress().getHostName() → C# Dns.GetHostEntry(((IPEndPoint) socket.RemoteEndPoint).Address.ToString()).HostName
|
|
34 java clazz.getName() → C# `type.Name`
|
|
35 java socket.getInputStream().read() → C# socket.Receive([格納する配列]) (intの長さが返る)
|
|
36 java ClassNotFoundException → C# TypeLoadException
|
0
|
37
|
2
|
38 ---
|
|
39
|
|
40 ## MessagePackが使用されていたクラス
|
|
41 * MessagePackDataGear
|
|
42 * RemoteMessage
|
|
43
|
|
44
|
|
45
|
|
46 ---
|
14
|
47 ## 実装を飛ばしている物(仮置きしているもの)
|
|
48 IncomingTcpConnetion 送られてくるデータを格納する配列のサイズ
|
|
49 PriorityThreadPoolExecutor ThreadPoolの優先度実装
|
|
50
|
|
51 ---
|
2
|
52 ## Tips
|
|
53 C#
|
|
54 object → 全ての継承元クラス
|
|
55 Type → 型情報
|
|
56 T → ジェネリクス
|
|
57
|
|
58 ---
|
|
59 javaのatomicintagerはc#に存在しない
|
0
|
60
|
|
61 intを読む, 代入するくらいは原始的が保証されているらしい
|
|
62 一度実装してみてダメなら
|
|
63 volatile修飾子をつける→読み書きがスレッドセーフになるが、コンパイラで最適化されない
|
|
64 https://ufcpp.net/study/csharp/misc_synchronize.html
|
|
65
|
|
66
|
|
67 intのインクリメントとかはこのメソッドを使ったほうがいいかも
|
|
68 https://docs.microsoft.com/en-us/dotnet/api/system.threading.interlocked?view=netcore-3.1
|
|
69
|
2
|
70 ---
|
0
|
71
|
|
72
|
|
73 java
|
2
|
74 ```public static <T> Class<T> [関数名] () { }```
|
|
75 → Class<T> は返り値の型
|
|
76 →その前の<T>はジェネリスクメソッドの型を表す
|
|
77
|
|
78 C#
|
|
79 ```public static Type [関数名]<T> () { }```
|
|
80 →Typeは返り値の型
|
|
81 →関数名の直後の<T>はジェネックメソッドの型を表す
|
|
82
|
|
83
|
|
84 java
|
|
85 int.class vs Intager.class
|
|
86 javaは独自でそれぞれの型についてプリミティブ型とクラス型が用意されているらしい…
|
|
87 https://stackoverflow.com/questions/22470985/integer-class-vs-int-class/22471247
|
|
88
|
|
89
|
|
90 java側のdatagear/WrapperClassいらないかも...
|
|
91 もうちょい調べる
|
|
92
|
|
93 ---
|
|
94 javaでは
|
|
95 ```T typeJava = null;```
|
|
96 はできるがC#では初期化でT型にnullを代入できない
|
|
97
|
|
98 T型の初期化は
|
|
99 ```T typeCs = default(T);```
|
|
100 とする。(T)は省略可能
|
|
101
|
|
102
|
|
103 ---
|
|
104 java getGenericSuperclass() → type.BaseTypeについて
|
|
105 どちらも直接のスーパクラス、直接の継承元のTypeを返す
|
|
106
|
|
107
|
|
108 javaの場合
|
|
109 Object クラス、インタフェース、プリミティブ型、または void を表す場合、null が返され、配列の場合はClassが帰ってくる
|
|
110
|
|
111
|
|
112 C#の場合
|
|
113 直接の継承しているTypeを返す、もし現在のTypeがobjectかインターフェースならnullが返る
|
|
114
|
|
115 ---
|
|
116 javaの場合
|
|
117 ジェネリスククラスの宣言時にジェネリスクの型宣言は省略できる
|
|
118 ex:``` Datagear dg;```
|
|
119
|
|
120
|
|
121 C#の場合
|
|
122 ジェネリッククラス宣言時にジェネリックの型宣言は省略できない
|
|
123 ex: ```Datagear<Type> dg; ```
|
|
124
|
|
125 ---
|
|
126
|
|
127 ~~MessagePackはjavaではread,writeにはジェネリックを使用できるが、
|
|
128 C#ではジェネリスクを使用することができない
|
|
129 →ラッパーか何かを挟んで型判断してread,writeするしかない?~~
|
|
130 C#で関数名が全然異なっていた...
|
|
131
|
|
132 javaリファレンス
|
|
133 http://msgpack.org/javadoc/current/org/msgpack/MessagePack.html#read(byte[],%20java.lang.Class)
|
|
134
|
|
135
|
|
136 C#README
|
|
137 https://github.com/neuecc/MessagePack-CSharp#quick-start
|
|
138
|
|
139 ---
|
|
140 C#のenumの扱いについて
|
|
141
|
|
142 C#のenumではstringは許容されていない
|
|
143 また、enum内でフィールド変数や関数を含めることはできないので、ヘルパークラスを実装してそちらを利用する必要がある
|
|
144
|
|
145 enum内でfor文などは使えないので、今回は別途関数を作成した
|
|
146 コンストラクタで使用するとか...?
|
|
147
|
|
148 ---
|
|
149 java HashMapとC# Dictionaryの違いについて
|
|
150 https://stackoverflow.com/questions/1273139/c-sharp-java-hashmap-equivalent
|
|
151 null周りなど違いがあるので注意
|
|
152
|
|
153 ---
|
|
154 ~~C#のBlockingCollectionは既定ではConcurrentQueue、つまりFIFOになっているが、特に使う理由はないのでConcurrentQueueを最初から利用することに~~
|
|
155 →いやブロッキングどうするねん
|
|
156 →やっぱり使う
|
|
157 https://www.atmarkit.co.jp/ait/articles/1802/07/news019.html
|
|
158 →使用後にDisposeしないといけない
|
|
159 →無理...?
|
|
160 →もしかしたらずっとBlockingCollection利用してるかも
|
|
161 →Getするところでlengthが0になったもしくは
|
|
162 破棄をしていたらdisposeする
|
|
163
|
15
|
164 #### BlockingCollection使用箇所(Dispoes処理)
|
2
|
165 * Connection
|
|
166 * DataGears → fin
|
|
167 * WaitList → fin
|
0
|
168
|
|
169
|
2
|
170 ---
|
|
171 C#だとsynchronized修飾子がないので
|
|
172 ```
|
|
173 private object syncObject = new object();
|
|
174
|
|
175 public void Function(){
|
|
176 lock (syncObject) {
|
|
177
|
|
178 }
|
|
179 }
|
|
180 ```
|
|
181 でロックをかける必要がある
|
|
182
|
|
183 ---
|
|
184 javaだとジェネリッククラスを型として変数宣言する際にはジェネリックの型宣言は必要ないが、
|
|
185 c#では変数宣言する際に型宣言が必須なので、今回はとりあえずobject型で宣言している。
|
|
186
|
|
187 DataGearの宣言は基本的にDataGear<object>で
|
|
188
|
|
189 ---
|
|
190 java側で出力されるsocket.getInetAddress().getHostName()
|
|
191 localhost:3333
|
|
192
|
|
193 ~~これと同様の結果をC#でも欲しい感じ~~
|
|
194
|
|
195 javaはSocketクラスが割となんでもしてくれる感じがあるが、
|
|
196 C#はSocket, Dns, IPAdress, IPEndPointとかなり役割が分散されているので注意
|
|
197
|
|
198 ---
|
|
199 daemon/Connection
|
|
200
|
|
201 Close()について
|
|
202 socket.shutdownでSocketShutdown.Bothで本当にあっているか
|
|
203
|
|
204 ---
|
0
|
205 java
|
2
|
206 socket.getChannel().write(buffer);について
|
|
207
|
|
208 javaのChannelではwrite(), read()などをByteBufferなどと一緒に使ってデータの送受信ができる。
|
|
209 Channelの開き方は、socketとは別にopenする必要があるので注意。
|
|
210
|
|
211 ---
|
|
212 christleに導入されているMessagePackのバージョンは0.6以前のもの
|
|
213 そのため、シリアライズするクラスには@Messageが必要になる
|
|
214 https://github.com/msgpack/msgpack-java/wiki/QuickStart-for-msgpack-java-0.6.x-(obsolete)
|
|
215
|
|
216 java版は0.7.xから仕様がかなり変わっているため注意が必要
|
|
217
|
|
218
|
|
219
|
|
220 C#版のMassagePackには日本人が作成したものを利用している(Unityとかでもサポートされているらしい)
|
|
221 https://github.com/neuecc/MessagePack-CSharp#quick-start
|
|
222
|
|
223
|
|
224 ---
|
|
225 javaとC#のenumの仕様はかなり異なっており
|
|
226 C#ではenumにメソッドを生やすことができない
|
|
227
|
|
228 ~~最初はヘルパークラスを実装することで対応しようとしたが、挙動的にenum各要素を初期化する必要があるとわかったため、独自にenumの挙動をするクラスを作成した~~
|
|
229
|
|
230 https://qiita.com/lilacs/items/167a73fbbfedf83eb51a
|
|
231 https://bleis-tift.hatenablog.com/entry/20080808/1218133517
|
|
232
|
|
233 必要なのはenumをintにする変換なので、C#ではenumをintにcastできるので廃止
|
|
234
|
|
235 ---
|
|
236 protected internalについて
|
|
237
|
|
238 ---
|
|
239 LinkedBlockingQueueとConcurrentQueueの特徴について
|
|
240
|
|
241 * LinkedBlockingQueue
|
|
242 * FIFO
|
|
243 * boolean contains(Object o): 要素の確認
|
|
244 * peek(): 先頭取得、削除しない
|
|
245 * poll(): 先頭取得、削除
|
|
246 * put(): 末尾に追加 完了するまでブロック
|
|
247 * add(): 末尾に追加 失敗時例外
|
|
248 * put, addの違いについては:https://docs.oracle.com/javase/jp/8/docs/api/java/util/concurrent/BlockingQueue.html#add-E-
|
|
249
|
|
250 * ConcurrentQueue
|
|
251 * FIFO
|
|
252 * スレッドセーフ
|
|
253 * Enqueue(): 末尾に追加
|
|
254 *
|
|
255
|
|
256 ---
|
|
257 Socketはaccept()するとその返り値にacceptされたsocketが返る
|
|
258 よってそれを変数に入れて利用する
|
|
259
|
|
260
|
|
261 ---
|
5
|
262 javaのThreadはThreadを継承して作成をする。
|
|
263 Threadの名前をつける必要あり
|
2
|
264
|
|
265
|
|
266 c#は
|
|
267 `Task task = Task.Run(() => MethodThread());
|
|
268 task.Run();`
|
5
|
269 (名前をつける必要なし)
|
2
|
270
|
|
271 ---
|
|
272 IncommingTcpConnectionなどのスレッドはAcceptThreadで一括でTask.Runする
|
|
273
|
|
274 ---
|
|
275 IncomingTcpConnetion
|
|
276
|
|
277 送られてくるデータ長がわからないので
|
|
278 とりあえず4096と置いている
|
|
279
|
|
280 ---
|
|
281 TCPで送受信するデータは、Remotemessage(Command), length, dataの順で入っている
|
|
282
|
|
283 PutCommand
|
|
284 Command
|
|
285 IncomingTcpConnection
|
|
286 を参照
|
|
287
|
5
|
288 ---
|
|
289 javaではserverSocketクラスがあり、listenerはこれを使えばいいが、c# 側にはない。
|
|
290
|
23
|
291 ここで注意するのが、javaではacceptでlistenを開始するが、C#ではListenでlistenを開始することに注意
|
2
|
292
|
|
293
|
|
294 ---
|
14
|
295 優先度付きThreadPoolについて
|
|
296 javaのほうでは実装されているが、現状処理が複雑なため一旦実装を飛ばす
|
|
297 優先度が実装されている理由についてはheartbeatを実装したかったと考えられる
|
|
298
|
|
299 Taskは内部でThreadPoolを作成しているらしい
|
|
300 https://oita.oika.me/2016/02/18/task-and-threadpool/
|
|
301
|
|
302 優先度をつけるならThreadPoolはTaskを利用できないかも
|
|
303
|
|
304 ---
|
15
|
305 Task.RunとTask.Factory.Startnewについて
|
|
306
|
|
307 無限ループさせるような、すぐには終了しないTaskについては
|
|
308 LongRunオプションをつける必要がある。
|
|
309
|
|
310 これは、Task.Runは裏でThreadPoolを作るが、この数がTask.Runの場合規定数(通常だと16(cpuに依存))に制限されており、無限ループのTaskも個の規定数にカウントされてしまうため
|
|
311 https://oita.oika.me/2016/02/18/task-and-threadpool/
|
|
312
|
|
313 それを避けるためにStartnewでTaskを作成する
|
|
314
|
|
315 https://qiita.com/chocolamint/items/3e2e4951ea0fa2ccd19e
|
|
316
|
|
317 ---
|
|
318 C#のTaskでのThreadPoolについて
|
|
319
|
|
320 https://stackoverflow.com/questions/35734051/c-sharp-task-thread-pool-running-100-tasks-across-only-10-threads
|
|
321
|
|
322 ---
|
27
|
323 lockのwaitとnotifyについて
|
|
324 Javaでは排他制御として`synchronized(lock)`(lockはobject型)を使用することで排他制御ができる。
|
|
325 解除にはlock.notifyなどを使う
|
|
326 https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Object.html#notify()
|
|
327
|
|
328 C#ではMoniterクラスの中にwaitやpulse関数があり、同じように使えるっぽい
|
|
329 https://docs.microsoft.com/en-us/dotnet/api/system.threading.monitor.pulse?view=net-5.0
|
|
330
|
|
331 ```java
|
|
332 Object lock = new Object;
|
|
333 synchronized(lock) {
|
|
334 lock.notify(); // lockの解除
|
|
335 }
|
|
336 ```
|
|
337
|
|
338 ```c#
|
|
339 objecy lockObj = new object;
|
|
340 lock(lockObj) {
|
|
341 Moniter.Pulse(lock);
|
|
342 }
|
|
343 ```
|
|
344
|
|
345 ---
|
2
|
346 ## TODO
|
|
347 * annotation → fin
|
|
348 * daemon
|
|
349 * connection → cgm要実装
|
5
|
350 * ChristieDaemon → fin
|
|
351 * AcceptThread → cgm要実装
|
2
|
352 * IncomingTcpConnection → CodeGearManager要実装
|
|
353 * OutboundTcpConnection → fin
|
27
|
354 * ThreadPoolExecutors 実装
|
2
|
355 * codegear
|
|
356 * CodeGear → InputDataGear要実装
|
|
357 * InputDataGear
|
14
|
358 * cgm要実装
|
2
|
359 * CodeGearManager
|
27
|
360 * cg要実装
|
|
361 * ThreadPoolExcuter要実装
|
14
|
362 * CodeGearExecutor
|
|
363 * cgm要実装
|
15
|
364 * cg要実装
|
2
|
365 * datagear
|
|
366 * command
|
|
367 * Command → fin
|
|
368 * CommandType → fin
|
|
369 * CommandBuilder → fin
|
|
370 * TakeCommand → CodeGear要実装
|
|
371 * その他のcommand → fin
|
|
372 * dg → fin
|
|
373 * DataGearManager → fin
|
|
374 * DataGears → fin
|
|
375 * WaitList → fin
|
|
376 * LocalDataGearManager → fin
|
27
|
377 * RemoteDataGearManager → fin
|
2
|
378
|
|
379
|
|
380
|
|
381
|