Java技術者のためのC#チートシート

#背景
これまでJavaをメインに仕事してきたのですが、ほとんど触れてこなかったC#を仕事で使うことになったので勉強しました。
似ているところもありますが、思想の違いや微妙な書き方の違いがあるので「これどう書くんだっけ？」が絶対に起きると思いましたので、よく使いそうなところをピックアップしてチートシートとしてまとめてみました。
細かいところは追々知っていこうと思います。

#使用するパッケージの宣言
##Java
呼び出し方が違う。

```java
import java.util.ArrayList;
```

##C＃
```c#
using System.Collections.Generic;
```

#パッケージの定義
宣言が違う。
また思想も違うのでネーミングは注意。

##Java
```java
package StudyPackage.com.anyplus
```

##C＃
```c#
namespace StudyPackage
// 思想が違うためドメインがない
```

#アクセス修飾子
Javaにはない`internal`や`protected internal`が存在する。
同じ修飾子でも思想の違いによることでアクセス可能範囲が異なる事にも注意。

| 修飾子 | Java | C# |
|:-:|:-:|:-:|
| public | どこからでもアクセス可能 | どこからでもアクセス可能 |
| protected | 同一のパッケージ、または派生したクラスからアクセス可能 | 派生したクラスからアクセス可能 |
| internal | 存在しない | 同一のアセンブリ(DLL)内でアクセス可能 |
| protected internal | 存在しない | 同一のアセンブリ(DLL)内、または格納しているクラスから派生した型からのみアクセス可能 |
| private | 同じクラス内からのみアクセス可能 | 同じクラス内からのみアクセス可能 |
| 指定なし<br>(default) | 同一のパッケージ内でアクセスが可能 | privateと同じ扱い |

**同一のアセンブリ(DLL)とは**
同一アセンブリとは、同一のexeファイルや、DLLファイルの事。
VisualStudioのソリューション内であれば、同一プロジェクトということらしい。

#継承
継承するときは`:`(コロン)を使用する。
オーバーライドさせたいメソッドには`virtual`を付け、オーバーライドする時は`override`をつける。
オーバーライドを禁止したい時、Javaならば`final`をメソッドに付与するが、C#の場合は`sealed`を付与する。(2020.07.21 更新)

##Java
```java
class Program {
    public static main(string[] args) {
        SubA cl = new SubA();
        cl.printStr1();    // SubAのprintStr1です
    }
}

class Base {
    public void printStr1(){
        System.out.println("BaseのprintStr1です");
    }
}

class SubA extends Base {
    public void printStr1(){
        System.out.println("SubAのprintStr1です");
    }
}
```

```java
class SubA extends Base {
    public final void printStr2(){   // このメソッドはオーバーライド不可
        System.out.println("SubAのprintStr1です");
    }
}
```

##C＃
```c#
class Program
{
    static void Main(string[] args)
    {
        SubA cl = new SubA();
        cl.printStr1();    // SubAのprintStr1です
    }
}

class Base {
    public virtual void printStr1(){
        Console.WriteLine("BaseのprintStr1です");
    }
}

class SubA : Base {
    public override void printStr1(){
        Console.WriteLine("SubAのprintStr1です");
    }
}
```

```c#
class SubA : Base {
    public override sealed void printStr1(){   // このメソッドはオーバーライド不可
        Console.WriteLine("SubAのprintStr1です");
    }
}
```

### virtual、overrideを付け忘れた場合
virtual、overrideを付けなかった場合、オーバーライドされない。
以下のような結果となる。(2020.08.13 更新)

```c#
// https://wandbox.org/permlink/bE71rRgU8ZLTktBS

namespace Wandbox
{
    class Program
    {
        static void Main(string[] args)
        {
            SubClass c1 = new SubClass();
            c1.Method1();   // Class Method1
            c1.Method2();   // Class Method2

            BaseClass c2 = new SubClass();
            c2.Method1();   // Base Method1　※オーバーライドされていないため
            c2.Method2();   // Class Method2
        }
    }

    public class BaseClass
     {
         public void Method1() 
         {
             Console.WriteLine("Base Method1");
         }

        public virtual void Method2() 
         {
             Console.WriteLine("Base Method2");
         }
    }


    public class SubClass : BaseClass
     {
         public void Method1() 
         {
            Console.WriteLine("Class Method1");
         }

        public override void Method2() 
         {
             Console.WriteLine("Class Method2");
         }
    }
}
```

#if文
違いなし。
Stringの比較は等値演算子でも値比較可能という違いがある。

##Java
```java
String strVal = "";

if("str".equals(strVal)){
    System.out.println("同じだよ");
} else
{
    System.out.println("違うよ");
}
```

##C＃
```c#
string strVal = "";

if("str" == strVal){  // 補足
    Console.WriteLine("同じだよ");
} else
{
    Console.WriteLine("違うよ");
}
```

**補足**
String型を参照型なのでJavaでは等値演算子で比較すると同じインスタンスを参照しているかの比較になるが、C#の場合は裏でstring.equalsを呼び出しているためこの書き方でも値の比較が可能。
`String.equals(String, StringComparison)`という比較方法の指定が可能なメソッドもあるため、コードを書く時はこちらを使用するのが無難と感じた…が、やっていることが同じならコード量の少ない等値演算子がベターか。（2020.07.17 更新）


参照→[String.Equalsメソッド - .NET Tips｜dobon.net](https://dobon.net/vb/dotnet/string/stringequals.html#equals)

#switch文
違いなし

##Java
```java
int month = 7;
switch (month)
{
case 1:
case 2:
case 3:
    System.out.println("1Q");
    break;
case 4:
case 5:
case 6:
    System.out.println("2Q");
    break;
case 7:
case 8:
case 9:
    System.out.println("3Q");
    break;
case 10:
case 11:
case 12:
    System.out.println("4Q");
    break;
default:
    System.out.println("不正な値です。");
    break;
}
```

##C＃
```c#
int month = 7;
switch (month)
{
case 1:
case 2:
case 3:
    Console.WriteLine("1Q");
    break;
case 4:
case 5:
case 6:
    Console.WriteLine("2Q");
    break;
case 7:
case 8:
case 9:
    Console.WriteLine("3Q");
    break;
case 10:
case 11:
case 12:
    Console.WriteLine("4Q");
    break;
default:
    Console.WriteLine("不正な値です。");
    break;
}
```

#for文
Javaの拡張for文はC#ではforeachとなる。

##Java
```java
for(int i = 0; i <= 10; i++){
    System.out.println(str);
}

String[] strArgs = {"1", "2"};
for(String str : strArgs){
    System.out.println(str);
}
```

##C＃
```c#
for(int i = 0; i <= 10; i++){
    Console.WriteLine(str);
}

string[] strArgs = {"1", "2"};
foreach(string str in strArgs){
    Console.WriteLine(str);
}
```

#while文
前判定、後判定共に違いなし。

##Java
```java
int i = 0;
while (i < 5) {
    System.out.println(i); //0,1,2,3,4が出力される
    i++;
}

do {
    System.out.println(i); //0,1,2,3,4が出力される
    i++;
} while (i < 5);
```

##C＃
```c#
int i = 0;
while (i < 5) {
    Console.WriteLine(i); //0,1,2,3,4が出力される
    i++;
}

do {
    Console.WriteLine(i); //0,1,2,3,4が出力される
    i++;
} while (i < 5);
```

#参考

[C#とJavaの比較](http://www.yo.rim.or.jp/~nag/cgi-bin/wiki.cgi?p=C%23%A4%C8Java%A4%CE%C8%E6%B3%D3)
[C# 入門](http://kaitei.net/csharp/)