You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免C#接口实现重复代码?类结构优化方案咨询

C#中复用接口实现代码的可行方案

现有大量密封类,各自继承不同抽象类,同时实现InterfaceWithProperties接口,当前每个类都重复编写接口成员的实现代码,违反DRY原则。需要找到类似“增强类型”的方式复用接口实现,避免重复代码。

以下是三种可行方案:

方案1:默认接口方法(C# 8.0+)

直接在接口中提供带私有成员存储的默认实现,实现类无需重复编写接口属性代码,直接复用接口逻辑。C# 10及以上支持接口私有字段,完美适配需求:

public interface InterfaceWithProperties
{
    // 接口私有字段存储属性值(C# 10+支持)
    private int _integerProperty;
    private string _stringProperty;

    [SomeAttribute]
    public int IntegerProperty 
    { 
        get => _integerProperty; 
        set => _integerProperty = value; 
    }

    [SomeAttribute]
    public string StringProperty 
    { 
        get => _stringProperty; 
        set => _stringProperty = value; 
    }
}

public abstract class AbstractClass1 
{
    public abstract Guid GuidProperty1 { get; set; }
}

public sealed class DerivativeClass1 : AbstractClass1, InterfaceWithProperties
{
    [TargetAttribute(ValueForDerivativeClass1)] 
    public override Guid GuidProperty1 { get; set; }
    // 无需重复编写接口属性,直接使用接口默认实现
}

这种方式最接近你期望的“augmentation”效果,代码简洁且无冗余。

方案2:组合模式(适配类)

创建封装接口实现的适配类,通过组合方式在密封类中复用逻辑,兼容性覆盖所有C#版本:

// 封装接口实现的适配类,仅需编写一次
public class PropertiesImplementation : InterfaceWithProperties
{
    [SomeAttribute]
    public int IntegerProperty { get; set; }

    [SomeAttribute]
    public string StringProperty { get; set; }
}

public sealed class DerivativeClass1 : AbstractClass1, InterfaceWithProperties
{
    private readonly PropertiesImplementation _props = new();

    [TargetAttribute(ValueForDerivativeClass1)] 
    public override Guid GuidProperty1 { get; set; }

    // 显式接口实现,转发调用给适配类
    [SomeAttribute]
    int InterfaceWithProperties.IntegerProperty 
    { 
        get => _props.IntegerProperty; 
        set => _props.IntegerProperty = value; 
    }

    [SomeAttribute]
    string InterfaceWithProperties.StringProperty 
    { 
        get => _props.StringProperty; 
        set => _props.StringProperty = value; 
    }
}

此方式代码量略多于默认接口方法,但兼容性更强,适合低版本C#项目。

方案3:源代码生成器(C# 9.0+)

通过编写源代码生成器,编译时自动为符合条件的密封类生成接口成员实现,完全消除重复代码:

生成器核心代码(简化版)

[Generator]
public class PropertiesGenerator : ISourceGenerator
{
    public void Execute(GeneratorExecutionContext context)
    {
        var interfaceSymbol = context.Compilation.GetTypeByMetadataName("YourNamespace.InterfaceWithProperties");
        if (interfaceSymbol == null) return;

        // 扫描所有实现接口的密封类
        foreach (var typeSymbol in context.Compilation.SyntaxTrees
            .SelectMany(tree => tree.GetRoot().DescendantNodes().OfType<ClassDeclarationSyntax>())
            .Select(syntax => context.Compilation.GetSemanticModel(syntax.SyntaxTree).GetDeclaredSymbol(syntax))
            .OfType<INamedTypeSymbol>()
            .Where(t => t.IsSealed && t.AllInterfaces.Contains(interfaceSymbol)))
        {
            // 自动生成属性实现代码
            var source = $$"""
            namespace {{typeSymbol.ContainingNamespace}}
            {
                public partial class {{typeSymbol.Name}}
                {
                    [SomeAttribute] public int IntegerProperty { get; set; }
                    [SomeAttribute] public string StringProperty { get; set; }
                }
            }
            """;
            context.AddSource($"{typeSymbol.Name}_Properties.g.cs", source);
        }
    }

    public void Initialize(GeneratorInitializationContext context) { }
}

密封类代码(仅需定义为partial)

public sealed partial class DerivativeClass1 : AbstractClass1, InterfaceWithProperties
{
    [TargetAttribute(ValueForDerivativeClass1)] 
    public override Guid GuidProperty1 { get; set; }
}

这种方式适合大量类的场景,编译时自动生成代码,无运行时开销。

内容的提问来源于stack exchange,提问作者SangYoung Ha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 03:55:13