クラスの定義
public class Person
{
// フィールド
private string _name;
private int _age;
// コンストラクタ
public Person(string name, int age)
{
_name = name;
_age = age;
}
// プロパティ
public string Name
{
get { return _name; }
set { _name = value; }
}
public int Age
{
get { return _age; }
set
{
if (value >= 0)
_age = value;
}
}
// メソッド
public void Greet()
{
Console.WriteLine($"こんにちは、{_name}です");
}
}
// 使用
var person = new Person("太郎", 25);
person.Greet();
Console.WriteLine(person.Name);
プロパティ
自動実装プロパティ
public class User
{
// 自動実装プロパティ
public string Name { get; set; }
public int Age { get; set; }
// 読み取り専用
public DateTime CreatedAt { get; } = DateTime.Now;
// init-only(初期化時のみ設定可能)
public string Id { get; init; }
// プライベートセッター
public int Count { get; private set; }
public void Increment() => Count++;
}
// オブジェクト初期化子
var user = new User
{
Name = "太郎",
Age = 25,
Id = "user-001"
};
計算プロパティ
public class Rectangle
{
public double Width { get; set; }
public double Height { get; set; }
// 計算プロパティ(式本体)
public double Area => Width * Height;
public double Perimeter => 2 * (Width + Height);
}
required プロパティ(C# 11)
public class Product
{
public required string Name { get; set; }
public required decimal Price { get; set; }
public string? Description { get; set; }
}
// 必須プロパティは初期化必須
var product = new Product
{
Name = "本",
Price = 1500
};
コンストラクタ
複数のコンストラクタ
public class Book
{
public string Title { get; }
public string Author { get; }
public int Price { get; }
public Book(string title) : this(title, "不明", 0)
{
}
public Book(string title, string author) : this(title, author, 0)
{
}
public Book(string title, string author, int price)
{
Title = title;
Author = author;
Price = price;
}
}
プライマリコンストラクタ(C# 12)
public class Person(string name, int age)
{
public string Name { get; } = name;
public int Age { get; } = age;
public void Greet() => Console.WriteLine($"こんにちは、{name}です");
}
static メンバー
public class Counter
{
private static int _count = 0;
public int Id { get; }
public Counter()
{
_count++;
Id = _count;
}
public static int GetCount() => _count;
}
var c1 = new Counter();
var c2 = new Counter();
Console.WriteLine(Counter.GetCount()); // 2
静的クラス
public static class MathUtils
{
public const double PI = 3.14159;
public static int Add(int a, int b) => a + b;
public static int Max(int a, int b) => a > b ? a : b;
}
// インスタンス化不可、静的メンバーのみ
int sum = MathUtils.Add(3, 5);
record
不変データ型を簡潔に定義します。
// record(参照型)
public record Person(string Name, int Age);
var person1 = new Person("太郎", 25);
var person2 = new Person("太郎", 25);
Console.WriteLine(person1 == person2); // true(値で比較)
Console.WriteLine(person1); // Person { Name = 太郎, Age = 25 }
// with式でコピー
var person3 = person1 with { Age = 26 };
// 分解
var (name, age) = person1;
record class と record struct
// record class(参照型、デフォルト)
public record class UserRecord(string Name, int Age);
// record struct(値型)
public record struct Point(int X, int Y);
// 読み取り専用record struct
public readonly record struct ImmutablePoint(int X, int Y);
struct(構造体)
値型の軽量なデータ構造です。
public struct Point
{
public int X { get; set; }
public int Y { get; set; }
public Point(int x, int y)
{
X = x;
Y = y;
}
public double DistanceTo(Point other)
{
return Math.Sqrt(Math.Pow(other.X - X, 2) + Math.Pow(other.Y - Y, 2));
}
}
Point p1 = new(0, 0);
Point p2 = new(3, 4);
Console.WriteLine(p1.DistanceTo(p2)); // 5
readonly struct
public readonly struct ImmutablePoint
{
public int X { get; }
public int Y { get; }
public ImmutablePoint(int x, int y)
{
X = x;
Y = y;
}
}
部分クラス
// File1.cs
public partial class Customer
{
public string Name { get; set; }
public string Email { get; set; }
}
// File2.cs(自動生成コードなど)
public partial class Customer
{
public void Validate()
{
// バリデーション処理
}
}
sealed クラス
継承を禁止します。
public sealed class FinalClass
{
public void DoSomething() { }
}
// public class Derived : FinalClass { } // エラー
実践例:銀行口座
public class BankAccount
{
private static int _nextAccountNumber = 1000;
public int AccountNumber { get; }
public string OwnerName { get; }
public decimal Balance { get; private set; }
public BankAccount(string ownerName, decimal initialBalance = 0)
{
AccountNumber = _nextAccountNumber++;
OwnerName = ownerName;
Balance = initialBalance;
}
public void Deposit(decimal amount)
{
if (amount <= 0)
throw new ArgumentException("金額は正の値である必要があります");
Balance += amount;
Console.WriteLine($"{amount:C}を入金しました。残高: {Balance:C}");
}
public bool Withdraw(decimal amount)
{
if (amount <= 0)
throw new ArgumentException("金額は正の値である必要があります");
if (amount > Balance)
{
Console.WriteLine("残高不足です");
return false;
}
Balance -= amount;
Console.WriteLine($"{amount:C}を出金しました。残高: {Balance:C}");
return true;
}
public override string ToString()
=> $"口座番号: {AccountNumber}, 名義: {OwnerName}, 残高: {Balance:C}";
}
// 使用
var account = new BankAccount("山田太郎", 10000);
account.Deposit(5000);
account.Withdraw(3000);
Console.WriteLine(account);
実践例:設定クラス(シングルトン)
public sealed class AppConfig
{
private static readonly Lazy<AppConfig> _instance =
new(() => new AppConfig());
public static AppConfig Instance => _instance.Value;
public string DatabaseConnection { get; set; } = "";
public bool DebugMode { get; set; }
public int MaxRetries { get; set; } = 3;
private AppConfig() { }
}
// 使用
AppConfig.Instance.DebugMode = true;
Console.WriteLine(AppConfig.Instance.MaxRetries);
まとめ
- クラスはフィールド、プロパティ、コンストラクタ、メソッドで構成
- 自動実装プロパティで簡潔に記述
initで初期化時のみ設定可能なプロパティrequiredで必須プロパティrecordで不変データ型を簡潔に定義structで軽量な値型を定義staticでクラスレベルのメンバーsealedで継承を禁止
次回は継承とインターフェースについて学びます。