0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

クラス間の依存関係のリストアップ

Last updated at Posted at 2025-11-28

クラス間の依存関係のリストアップ

はじめに

筆者は下記記事でC#の自動クラス図作成ツールを公開しています。初リリース時のツールでは検出できていない依存が多く、種類を整理するためにまとめました。初心者の勉強にもなると思います。

ちなみに、ここで紹介している依存はすべて私のアプリで(たぶん)拾えます。ぜひツールを使ってみてください。
Roslynを使用した静的解析により検出してます。Roslynを使用した検出方法をメモ書きしていますが気にしないでください。

依存関係一覧

No. 依存の種類 説明
1 継承 基底クラスへの依存
2 インターフェース実装 実装インターフェースへの依存
3 フィールド・プロパティの型 メンバー変数の型への依存
4 メソッドシグネチャ 戻り値型・パラメータ型への依存
5 オブジェクト生成(new) インスタンス生成による依存
6 静的メソッド呼び出し 静的メソッドを持つクラスへの依存
7 拡張メソッド呼び出し 拡張メソッド定義クラスへの依存
8 静的プロパティ・フィールドアクセス 静的メンバーを持つクラスへの依存
9 ジェネリック型引数 ジェネリックの型パラメータへの依存
10 例外処理(catch) catch句の例外型への依存
11 例外スロー(throw) throw文での例外型への依存
12 型キャスト キャスト先の型への依存
13 as演算子 型変換先への依存
14 is演算子・パターンマッチング 型チェック対象への依存
15 typeof演算子 リフレクション対象型への依存
16 属性(Attribute) 属性クラスへの依存
17 var宣言(型推論) 推論された型への依存
18 インスタンスメソッド呼び出し 呼び出し元オブジェクトの型への依存
19 ラムダ式内のメンバーアクセス ラムダ内で使用される型への依存
20 配列型 配列要素の型への依存
21 タプル型 タプル要素の型への依存
22 switch式のパターンマッチング switch式内の型への依存
23 nameof演算子 nameof対象の型への依存
24 default演算子 デフォルト値の型への依存
25 ジェネリック制約(where句) 制約に指定された型への依存

各依存関係の詳細

1. 継承

基底クラスを継承することで、そのクラスへの依存関係が生じます。

public class CustomerRepository : BaseRepository
{
    // CustomerRepository は BaseRepository に依存
}

検出方法: INamedTypeSymbol.BaseType から基底クラスを取得


2. インターフェース実装

インターフェースを実装することで、そのインターフェースへの依存関係が生じます。

public class CustomerService : ICustomerService, IDisposable
{
    // CustomerService は ICustomerService と IDisposable に依存
}

検出方法: INamedTypeSymbol.Interfaces から実装インターフェースを取得


3. フィールド・プロパティの型

クラスのフィールドやプロパティの型として使用されるクラスへの依存です。

public class OrderService
{
    private readonly ICustomerRepository _customerRepository;  // 依存: ICustomerRepository
    public OrderDto CurrentOrder { get; set; }  // 依存: OrderDto
    private List<ProductInfo> _products;  // 依存: List<ProductInfo>, ProductInfo
}

検出方法:

  • IFieldSymbol.Type からフィールドの型を取得
  • IPropertySymbol.Type からプロパティの型を取得

4. メソッドシグネチャ

メソッドの戻り値型やパラメータ型への依存です。

public class OrderService
{
    // 依存: OrderDto(戻り値), int(プリミティブのため除外), CustomerInfo(パラメータ)
    public OrderDto CreateOrder(int customerId, CustomerInfo info)
    {
        // ...
    }
}

検出方法:

  • IMethodSymbol.ReturnType から戻り値型を取得
  • IMethodSymbol.Parameters からパラメータ型を取得

5. オブジェクト生成(new)

new 演算子でインスタンスを生成する際の依存です。

public void ProcessOrder()
{
    var customer = new CustomerDto();  // 依存: CustomerDto
    var orders = new List<OrderInfo>();  // 依存: List<OrderInfo>, OrderInfo
}

検出方法: ObjectCreationExpressionSyntax を解析し、GetSymbolInfo から型を取得


6. 静的メソッド呼び出し

静的メソッドを呼び出すことで、そのメソッドを持つクラスへの依存が生じます。

public void ValidateData(string input)
{
    if (ValidationHelper.IsValid(input))  // 依存: ValidationHelper
    {
        // ...
    }
}

検出方法: InvocationExpressionSyntax から IMethodSymbol を取得し、IsStatic をチェック


7. 拡張メソッド呼び出し

拡張メソッドを使用することで、その拡張メソッドを定義しているクラスへの依存が生じます。

public void ProcessJson(JObject jObject)
{
    // 依存: JObjectExtensions(AssignIfExistsを定義しているクラス)
    jObject.AssignIfExists<string>("key", val => Process(val));
}

検出方法: IMethodSymbol.IsExtensionMethod をチェックし、ContainingType を取得


8. 静的プロパティ・フィールドアクセス

静的なプロパティやフィールドにアクセスすることで依存が生じます。

public void ConfigureSettings()
{
    var apiKey = AppSettings.ApiKey;  // 依存: AppSettings
    var format = FormatKeys.Id;  // 依存: FormatKeys
}

検出方法: MemberAccessExpressionSyntax から IPropertySymbol または IFieldSymbol を取得し、IsStatic をチェック


9. ジェネリック型引数

ジェネリック型やメソッドの型引数として指定される型への依存です。

public void ProcessData()
{
    var list = new List<CustomerDto>();  // 依存: List<T>, CustomerDto
    var dict = new Dictionary<string, OrderInfo>();  // 依存: Dictionary<K,V>, OrderInfo
    
    var result = SomeMethod<ProductData>();  // 依存: ProductData
}

検出方法:

  • INamedTypeSymbol.TypeArguments からジェネリック型引数を取得
  • IMethodSymbol.TypeArguments からメソッドの型引数を取得

10. 例外処理(catch)

catch句で例外型を指定することで、その例外型への依存が生じます。

public void ProcessData()
{
    try
    {
        // ...
    }
    catch (MyException ex)  // 依存: MyException
    {
        // ...
    }
    catch (InvalidOperationException)  // 依存: InvalidOperationException
    {
        // ...
    }
}

検出方法: CatchClauseSyntax.Declaration.Type から例外型を取得


11. 例外スロー(throw)

throw文で例外をスローする際の依存です。

public void ValidateInput(string input)
{
    if (string.IsNullOrEmpty(input))
    {
        throw new ValidationException("Input is required");  // 依存: ValidationException
    }
    
    throw new MyException($"Error: {input}", ex);  // 依存: MyException
}

検出方法: throw文内の ObjectCreationExpressionSyntax を検出


12. 型キャスト

明示的な型キャストによる依存です。

public void ProcessData(object data)
{
    var customer = (CustomerDto)data;  // 依存: CustomerDto
    var order = (IOrderInfo)GetOrder();  // 依存: IOrderInfo
}

検出方法: CastExpressionSyntax.Type から型を取得


13. as演算子

安全な型変換(as演算子)による依存です。

public void ProcessData(object data)
{
    var customer = data as CustomerDto;  // 依存: CustomerDto
    if (customer != null)
    {
        // ...
    }
}

検出方法: BinaryExpressionSyntaxIsKind(SyntaxKind.AsExpression) をチェック


14. is演算子・パターンマッチング

型チェックとパターンマッチングによる依存です。

public void ProcessData(object data)
{
    // 従来のis演算子
    if (data is CustomerDto)  // 依存: CustomerDto
    {
        // ...
    }
    
    // パターンマッチング
    if (data is OrderInfo order)  // 依存: OrderInfo
    {
        ProcessOrder(order);
    }
    
    // プロパティパターン
    if (data is ProductData { IsActive: true })  // 依存: ProductData
    {
        // ...
    }
}

検出方法:

  • BinaryExpressionSyntaxIsKind(SyntaxKind.IsExpression) をチェック
  • IsPatternExpressionSyntax からパターン内の型を取得

15. typeof演算子

リフレクションで型情報を取得する際の依存です。

public void RegisterType()
{
    var type = typeof(CustomerDto);  // 依存: CustomerDto
    container.Register(typeof(ICustomerService));  // 依存: ICustomerService
}

検出方法: TypeOfExpressionSyntax.Type から型を取得


16. 属性(Attribute)

クラスやメンバーに付与される属性による依存です。

[Serializable]  // 依存: SerializableAttribute
[CustomValidation(ErrorMessage = "Invalid")]  // 依存: CustomValidationAttribute
public class CustomerDto
{
    [Required]  // 依存: RequiredAttribute
    [StringLength(100)]  // 依存: StringLengthAttribute
    public string Name { get; set; }
    
    [Obsolete("Use NewMethod instead")]  // 依存: ObsoleteAttribute
    public void OldMethod() { }
}

検出方法: AttributeSyntax から GetSymbolInfo で属性クラスを取得


17. var宣言(型推論)

var宣言で型推論される際の依存です。

public void ProcessData()
{
    var customer = new CustomerDto();  // 依存: CustomerDto(型推論)
    var result = GetOrderData();  // 依存: GetOrderDataの戻り値型
    var list = GetCustomers();  // 依存: List<CustomerInfo>(推論結果)
}

検出方法: VariableDeclarationSyntax.Type.IsVar をチェックし、Initializer.Value の型を取得


18. インスタンスメソッド呼び出し

インスタンスのメソッドを呼び出すことで、そのインスタンスの型への依存が生じます。

public void ProcessOrder(CustomerRepository repository)
{
    var customer = repository.GetCustomer(id);  // 依存: CustomerRepository
    
    var order = new OrderService();
    order.ProcessOrder(customerId);  // 依存: OrderService
}

検出方法: InvocationExpressionSyntaxExpressionMemberAccessExpressionSyntax の場合、左辺の型を取得


19. ラムダ式内のメンバーアクセス

ラムダ式内で使用される型への依存です。

public void ProcessData(JObject jObject)
{
    // ラムダ式内でtoolDataのメンバーにアクセス
    jObject.AssignIfExists<string>("key", val => toolData.GlobalId = val);
    //                                            ^^^^^^^^ toolDataの型への依存
    
    var filtered = customers.Where(c => c.IsActive);  // 依存: Customer
    
    var mapped = orders.Select(o => new OrderDto 
    { 
        Id = o.Id,  // 依存: Order
        Total = Calculator.CalculateTotal(o)  // 依存: Calculator
    });
}

検出方法: SimpleLambdaExpressionSyntaxParenthesizedLambdaExpressionSyntax 内の DescendantNodes() を解析


20. 配列型

配列の要素型への依存です。

public void ProcessData()
{
    var customers = new CustomerDto[10];  // 依存: CustomerDto
    string[] names = GetNames();  // 依存: string(プリミティブのため除外)
    
    IOrderInfo[] orders = new OrderInfo[5];  // 依存: IOrderInfo, OrderInfo
}

検出方法: IArrayTypeSymbol.ElementType から要素型を取得


21. タプル型

タプルの要素型への依存です。

public (CustomerDto customer, OrderInfo order) GetData()
{
    // 依存: CustomerDto, OrderInfo
    return (new CustomerDto(), new OrderInfo());
}

public void ProcessData()
{
    var (customer, order) = GetData();  // タプル分解
    var tuple = (Name: "John", Age: 30);  // 値タプル
}

検出方法: タプル型の要素を再帰的に処理


22. switch式のパターンマッチング

switch式内で使用される型への依存です。

public string ProcessData(object data)
{
    return data switch
    {
        CustomerDto customer => customer.Name,  // 依存: CustomerDto
        OrderInfo order => order.OrderNumber,   // 依存: OrderInfo
        ProductData product => product.Code,    // 依存: ProductData
        _ => "Unknown"
    };
}

検出方法: SwitchExpressionSyntaxSwitchExpressionArmSyntax 内のパターンを解析


23. nameof演算子

nameof演算子で参照される型への依存です。

public void LogError()
{
    var typeName = nameof(CustomerDto);  // 依存: CustomerDto(弱い依存)
    var propName = nameof(CustomerDto.Name);  // 依存: CustomerDto
    
    Console.WriteLine($"Error in {nameof(OrderService)}");  // 依存: OrderService
}

検出方法: InvocationExpressionSyntaxnameof を検出し、引数から型を取得


24. default演算子

default演算子で型を指定する際の依存です。

public CustomerDto GetCustomer()
{
    return default(CustomerDto);  // 依存: CustomerDto
}

public void ProcessData<T>()
{
    var value = default(T);  // ジェネリック型パラメータ
    return default;  // C# 7.1以降、型推論
}

検出方法: DefaultExpressionSyntax から型を取得


25. ジェネリック制約(where句)

ジェネリック型の制約に指定される型への依存です。

public class Repository<T> where T : BaseEntity, IEntity
{
    // 依存: BaseEntity, IEntity
}

public void ProcessData<T>(T data) 
    where T : ICustomerInfo, IDisposable
{
    // 依存: ICustomerInfo, IDisposable
}

検出方法: TypeParameterConstraintClauseSyntax から制約型を取得



参考リンク

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?