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

如何在C#接口中处理可选可变参数,实现强类型支持?

解决方案

方案1:使用方法重载(最直接的类型安全实现)

针对不同参数组合定义重载方法,彻底避免params object[]的类型解析问题,调用时IDE会提供精确的智能提示。

先调整基础接口,允许实现类按需添加重载:

public interface IMapper<TDtoType, TDbType>
{
    TDtoType MapEntityToDto(TDbType toBeMapped);
    TDbType MapDtoToEntity(TDtoType toBeMapped);
}

在PositionMapper中实现对应参数的重载:

public class PositionMapper : IMapper<PositionDto, Position>
{
    public PositionDto MapEntityToDto(Position toBeMapped) => new()
    {
        StorageArea = toBeMapped.Storage.Name,
        Width = toBeMapped.Width,
        Height = toBeMapped.Height,
        Depth = toBeMapped.Depth
    };

    // 基础重载:仅传入必填的Storage
    public Position MapDtoToEntity(PositionDto toBeMapped, Storage storage)
        => MapDtoToEntity(toBeMapped, storage, Guid.Empty, null);

    // 重载:传入Storage + Id
    public Position MapDtoToEntity(PositionDto toBeMapped, Storage storage, Guid id)
        => MapDtoToEntity(toBeMapped, storage, id, null);

    // 完整参数重载:传入所有可能参数
    public Position MapDtoToEntity(PositionDto toBeMapped, Storage storage, Guid id, Carrier? carrier) => new()
    {
        Id = id,
        Depth = toBeMapped.Depth,
        Width = toBeMapped.Width,
        Height = toBeMapped.Height,
        Storage = storage ?? throw new ArgumentNullException(nameof(storage)),
        Carrier = carrier
    };

    // 显式实现接口的无参方法(若不需要可标记为[Obsolete]或抛出异常)
    Position IMapper<PositionDto, Position>.MapDtoToEntity(PositionDto toBeMapped)
        => throw new NotImplementedException("请传入必要的Storage参数");
}

调用示例:

var mapper = new PositionMapper();
var basicPosition = mapper.MapDtoToEntity(dto, storageInstance);
var positionWithId = mapper.MapDtoToEntity(dto, storageInstance, Guid.NewGuid());
var positionWithCarrier = mapper.MapDtoToEntity(dto, storageInstance, Guid.NewGuid(), carrierInstance);

方案2:使用参数对象封装(适合参数较多的场景)

把可变参数封装成强类型参数类,既保持方法签名简洁,又能实现类型安全和可选参数控制。

首先定义参数类:

public class PositionMappingParams
{
    // 必填参数,使用C# 10+的required关键字强制赋值
    public required Storage Storage { get; init; }
    // 可选参数,设置默认值
    public Guid Id { get; init; } = Guid.Empty;
    public Carrier? Carrier { get; init; } = null;
}

修改接口与实现类:

public interface IMapper<TDtoType, TDbType, TMappingParams>
{
    TDtoType MapEntityToDto(TDbType toBeMapped);
    TDbType MapDtoToEntity(TDtoType toBeMapped, TMappingParams mappingParams);
}

public class PositionMapper : IMapper<PositionDto, Position, PositionMappingParams>
{
    public PositionDto MapEntityToDto(Position toBeMapped) => new()
    {
        StorageArea = toBeMapped.Storage.Name,
        Width = toBeMapped.Width,
        Height = toBeMapped.Height,
        Depth = toBeMapped.Depth
    };

    public Position MapDtoToEntity(PositionDto toBeMapped, PositionMappingParams mappingParams) => new()
    {
        Id = mappingParams.Id,
        Depth = toBeMapped.Depth,
        Width = toBeMapped.Width,
        Height = toBeMapped.Height,
        Storage = mappingParams.Storage ?? throw new ArgumentNullException(nameof(mappingParams.Storage)),
        Carrier = mappingParams.Carrier
    };
}

调用示例(利用对象初始化器按需赋值):

var mapper = new PositionMapper();
var position = mapper.MapDtoToEntity(dto, new PositionMappingParams
{
    Storage = storageInstance,
    Carrier = carrierInstance // 可选参数按需添加
});

方案3:结合可选参数与泛型接口(平衡通用性和类型安全)

如果希望接口保持通用性,同时支持强类型可选参数,可以直接在接口方法中定义带默认值的强类型参数:

修改接口:

public interface IMapper<TDtoType, TDbType>
{
    TDtoType MapEntityToDto(TDbType toBeMapped);
    TDbType MapDtoToEntity(TDtoType toBeMapped, Storage storage, Guid id = default, Carrier? carrier = null);
}

实现类:

public class PositionMapper : IMapper<PositionDto, Position>
{
    public PositionDto MapEntityToDto(Position toBeMapped) => new()
    {
        StorageArea = toBeMapped.Storage.Name,
        Width = toBeMapped.Width,
        Height = toBeMapped.Height,
        Depth = toBeMapped.Depth
    };

    public Position MapDtoToEntity(PositionDto toBeMapped, Storage storage, Guid id = default, Carrier? carrier = null) => new()
    {
        Id = id,
        Depth = toBeMapped.Depth,
        Width = toBeMapped.Width,
        Height = toBeMapped.Height,
        Storage = storage ?? throw new ArgumentNullException(nameof(storage)),
        Carrier = carrier
    };
}

调用示例(支持命名参数跳过可选值):

var mapper = new PositionMapper();
// 跳过Id参数,直接指定Carrier
var position = mapper.MapDtoToEntity(dto, storageInstance, carrier: carrierInstance);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 01:57:19