[C#] メソッド/コンストラクター/null/LINQについて


**メソッド名は引数が違えば同じ名前でもOK**

```C#:
using System;

namespace ClassSample
{
    class Program
    {
        static void Main(string[] args)
        {
            var scores = new int[] { 55, 70, 43, 79, 17, 31, 48 };
            var total = ArrayUtils.Total(scores);
            Console.WriteLine(total);

            var scores2 = new double[] { 5.8, 6.2, 5.9, 2.1, 6.6, 9.5, 3.8 };
            var total2 = ArrayUtils.Total(scores2);
            Console.WriteLine(total2);
        }

        static class ArrayUtils
        {
            //①int型の配列の数値の合計を求める
            public static int Total(int [] numbers)
            {
                var total = 0;
                foreach (var n in numbers)
                {
                    total += n;
                }
                return total;
            }

            // ②double型の配列内の数値の合計を求める
            public static double Total(double[] numbers)   //同じメソッド名で引数が異なる
            {
                var total = 0.0;
                foreach (var n in numbers)
                {
                    total += n;
                }
                return total;
            }

        }
    }
}
```

**メソッドの省力可能な引数**

```C#:ClassSample
using System;

namespace ClassSample
{
    class Program
    {
        static void Main(string[] args)
        {
            var person = new Person
            {
                FirstName = "たかし",
                LastName = "小林"
            };
            var name1 = person.AddTitle("先生");  //引数を指定して呼び出す
            var name2 = person.AddTitle();  //引数を省略して呼び出す
            Console.WriteLine(name1);
            Console.WriteLine(name2);
        }
    }

    class Person
        {
            public string FirstName { get; set; }
            public string LastName { get; set; }

            public string AddTitle(string title = "様")  //titleは省力可能な引数
            {
                return $"{LastName}{FirstName} {title}";
            }
           
        }
}
```

**コンストラクターの定義方法**

```C#:ClassSample
using System;

namespace ClassSample
{
    class Program
    {
        static void Main(string[] args)
        {
            var mypet = new VirtualPet();   //インスタンス生成時にコンストラクタが呼び出される
            Console.WriteLine($"Name: {mypet.Name}");
            Console.WriteLine($"Mood: {mypet.Mood}");
            Console.WriteLine($"Energy: {mypet.Energy}");

        }
    }

    class VirtualPet
        {
            public string Name { get; set; }
            public int Mood { get; set; }
            public int Energy { get; set; }

            public VirtualPet() //コンストラクターの名前はクラスと同じにする
            {
                Name = "エイミー";
                Mood = 5;
                Energy = 100;
            }
        }
}
```
**引数のあるコンストラクター**

```C#:ClassSample
using System;

namespace ClassSample
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.Write("名前を入力してください⇒");
            var name = Console.ReadLine();
            var mypet = new VirtualPet(name);   //引数を指定したコンストラクターが呼ばれる
            Console.WriteLine($"Name: {mypet.Name}");
            Console.WriteLine($"Mood: {mypet.Mood}");
            Console.WriteLine($"Energy: {mypet.Energy}");

        }
    }

class VirtualPet
        {
            public string Name { get; set; }
            public int Mood { get; set; }
            public int Energy { get; set; }

            public VirtualPet(string name) //コンストラクターの名前はクラスと同じにする
            {
                Name = name;
                Mood = 5;
                Energy = 100;
            }
        }
}
```

**プロパティに特別な動作を加える**

```C#:
class Book
    {
        public static int Count { get; set; }

        public static void ClearCount()
        {
            Count = 0;
        }

        public string Title { get; set; }
        public string Auther { get; set; }
        public int Pages { get; set; }

        int _rating;    //フィールドの定義

        public int Rating   //プロパティの定義
        {
            //getアクセサ、setアクセサー内は、メソッドと同様、複数行の処理が欠ける
            get //getアクセサーの定義
            {
                return _rating; //参照時にこのコードが実行される
            }
            set //setアクセサーの定義
            {
                if (value <= 1) //1以下の値はすべて1をセット
                {
                    _rating = 1;
                }
                else if (value >= 6) //6以上の値はすべて5をセット
                {
                    _rating = 5;
                }
                else
                {
                    _rating = value;
                }
            }
        }
```
**構造体の定義方法**

```C#:ClassSample
using System;

namespace ClassSample
{
    //card構造体
    struct Card
    {
        static void Main(string[] args)
        {
            var card = new Card('S', 8);    //構造体もnew演算子でインスタンスを生成する
            card.Print();
            if (card.Suit == 'D')
            {
                Console.WriteLine("ダイヤです");
            }
            else
            {
                Console.WriteLine("ダイヤではありません");
            }
        }

        public char Suit { get; private set; }  //読み取り専用プロパティ
        public int Number { get; private set; } //読み取り専用プロパティ

        //コンストラクター
        public Card(char suit, int number)
        {
            Suit = suit;
            Number = number;
        }

        //メソッド
        public void Print()
        {
            var s = "";
            switch (Suit)
            {
                case 'H':
                    s = "ハート";
                    break;
                case 'D':
                    s = "ダイヤ";
                    break;
                case 'S':
                    s = "スペード";
                    break;
                case 'C':
                    s = "クラブ";
                    break;
            }
            Console.WriteLine($"{s} {Number}");
        }
    }
}
```
**列挙型の定義方法**

```C#:ClassSample
using System;

namespace ClassSample
{
    enum CardSuit
    {
        Club,
        Spade,
        Heart,
        Diamond
    }

    //card構造体
    struct Card
    {
        static void Main(string[] args)
        {
            var card = new Card(CardSuit.Heart, 8);
            card.Print();
            if (card.Suit == CardSuit.Diamond)
            {
                Console.WriteLine("ダイヤです");
            }
            else
            {
                Console.WriteLine("ダイヤではありません");
            }
        }

        public CardSuit Suit { get; private set; }  //SuitはCardSuit型のプロパティ
        public int Number { get; private set; }

        //コンストラクター
        public Card(CardSuit suit, int number)  //第一引数ではCardSuit型を受け取る
        {
            Suit = suit;
            Number = number;
        }

        //メソッド
        public void Print()
        {
            var s = "";
            switch (Suit)
            {
                case CardSuit.Heart:
                    s = "ハート";
                    break;
                case CardSuit.Diamond:
                    s = "ダイヤ";
                    break;
                case CardSuit.Spade:
                    s = "スペード";
                    break;
                case CardSuit.Club:
                    s = "クラブ";
                    break;
            }
            Console.WriteLine($"{s} {Number}");
        }
    }
}
```
**null**
nullはオブジェクトが生成されなかった状態や、指定した条件に合うオブジェクトが見つからなかった状態を表すときによく使われる

```C#:ClassSample
using System;

namespace ClassSample
{
    class Program
    {
        static void Main()
        {
            var book = GetBook();   //nullかどうかでGetBookが成功したかどうかを判断
            if (book == null)
            {
                Console.WriteLine("bookオブジェクトは生成できませんでした");
            }
            else
            {
                Console.WriteLine($"{book.Title} {book.Auther}");
            }
        }
        private static Book GetBook()
        {
            var line = Console.ReadLine();
            var items = line.Split(',');
            if (items.Length != 2)
            {
                return null;    //入力したデータが正しくない場合はnullを返す
            }
            var book = new Book
            {
                Title = items[0],
                Auther = items[1],
            };
            return book;
        }
    }

    class Book
    {
        public string Title { get; set; }
        public string Auther { get; set; }
        public int Pages { get; set; }
        public int Rating { get; set; }

    }
}
```
**Listの使い方**

```C#:ClassSample
using System;
using System.Collections.Generic;   //Listを使う際に必要

namespace ClassSample
{
    class Program
    {
        static void Main()
        {
            var lines = new List<string>
            {
                "おはよう",
                "こんにちは",
                "こんばんは"
            };
            lines.Add("おやすみ");  //Listに追加する際はAddを使う
            lines.Add("さようなら");
            lines.RemoveAt(2);  //リストから指定の要素を削除する

            foreach (var s in lines)
            {
                Console.WriteLine(s);
            }

            var count = lines.Count;    //リストの要素数を取得するにはCountを使う
            Console.WriteLine(count);

            lines.Clear();  //すべての要素を削除するときはClearメソッドを使う
            Console.WriteLine($"{lines.Count}");

        }
    }
}
```

```C#:ClassSample
using System;
using System.Collections.Generic;

namespace ClassSample
{
    class Program
    {
        static void Main()
        {
            var books = new List<Book>();   //Book型のリストを生成
            var book1 = new Book("吾輩は猫である", "夏目漱石", 620, 4);
            books.Add(book1);   //1冊目を追加
            var book2 = new Book("人間失格", "太宰治", 300, 5);
            books.Add(book2);   //2冊目を追加

            //省略もできる
            //books.Add(new Book("吾輩は猫である", "夏目漱石", 620, 4));
            //books.Add(new Book("人間失格", "太宰治", 300, 5));

            foreach (var book in books)
            {
                Console.WriteLine($"{book.Title} {book.Auther} {book.Pages} {book.Rating}");
            }
        }   
    }

    class Book
    {
        public string Title { get; set; }
        public string Auther { get; set; }
        public int Pages { get; set; }
        public int Rating { get; set; }

        public Book(string title, string auther, int pages, int rating)
        {
            Title = title;
            Auther = auther;
            Pages = pages;
            Rating = rating;
        }
    }
}
```
LINQ
---
**Whereメソッドとラムダ式**

例１
```C#:ClassSample
using System;
using System.Collections.Generic;
using System.Linq;  // LINQを使うのに必要

namespace ClassSample
{
    class Program
    {
        static void Main()
        {
            var nums = new List<int> { 12, 69, 38, 32, 63, 55, 71, 93, 39, 48 };

            var query = nums.Where(x => x >= 50);   //Whereは条件に一致した要素を抜き出す
            foreach (var n in query)
            {
                Console.WriteLine(n);
            }
        }   
    }
}
```
例２

```C#:ClassSample
using System;
using System.Collections.Generic;
using System.Linq;  // LINQを使うのに必要

namespace ClassSample
{
    class Program
    {
        static void Main()
        {
            var words = new List<string>
            {
                "effect", "access", "condition", "sign", "profit", "line", "result"
            };
            var query = words.Where(x => x.Length == 6);    //長さ6の文字列だけ取り出す
            foreach (var word in query)
            {
                Console.WriteLine(word);
            }
        }   
    }
}
```
**Selectメソッド**
Selectメソッドを使えばコレクションの各要素を別の値に変更できる

```C#:ClassSample
using System;
using System.Collections.Generic;
using System.Linq;  // LINQを使うのに必要

namespace ClassSample
{
    class Program
    {
        static void Main()
        {
            var nums = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, };
            var query = nums.Select(x => x * 2);    //各要素を2倍する
            foreach (var n in query)
            {
                Console.WriteLine(n);
            }
        }   
    }
}
```

各要素の長さを求める
var query = words.Select(x => x.Length);

１つの要素を全て取り出す( ↓タイトルを取り出す)
var query = words.Select(x => x.Title);

**OrderByメソッド / OrderByDescendingメソッド**

コレクション内のデータを指定した順番で取り出せる

```C#:ClassSample
using System;
using System.Collections.Generic;
using System.Linq;  // LINQを使うのに必要

namespace ClassSample
{
    class Program
    {
        static void Main()
        {
            var nums = new int[] { 6, 4, 3, 2, 5, 1, 9, 8, 7, };
            var query = nums.OrderBy(x => x);    //小さい順に並べる
            foreach (var n in query)
            {
                Console.WriteLine(n);
            }
        }   
    }
}
```
大きい順に並べる
var query = nums.OrderByDescending(x => x);

**複数のLINQメソッドを連結させることも可能**
ドットでつなげる
var query = books.Where(x => x.Rating == 5).Select(x => x.Title);

Take() で先頭から指定した個数を取り出す

```C#:ClassSample
using System;
using System.Collections.Generic;
using System.Linq;  // LINQを使うのに必要

namespace ClassSample
{
    class Program
    {
        static void Main()
        {
            var nums = new int[] { 6, 4, 3, 2, 5, 1, 9, 8, 7, };
            var query = nums.OrderByDescending(x => x)
                            .Take(3);    //先頭の3つを取り出す
            foreach (var n in query)
            {
                Console.WriteLine(n);
            }
        }   
    }
}
```
Distinctは重複した要素を排除できる
var query = books.Where(x => x.Rating >= 4).Select(x => x.Auther).Distinct;

Anyは条件を満たす要素が含まれているか判断できる
var any = nums.Any(x => x < 0); //マイナス値があるか調べる


**IEnumerable<T>を配列に変換するにはToList / ToArrayメソッドを使用する**
ToList

```C#:ClassSample
using System;
using System.Collections.Generic;
using System.Linq;  // LINQを使うのに必要

namespace ClassSample
{
    class Program
    {
        static void Main()
        {
            var nums = new int[] { 62, 4, 34, 26, 15, 51, 97, 84, 72, };
            var list = nums.Where(x => x <= 10)
                            .ToList();    //Whereの結果をList<int>に変換する
            Console.WriteLine(list[0]);
        }   
    }
}
```
ToArray()はString[]に変更できる
var array = words.OrderBy(x => x).Array();