c# 泛型函数的使用

以下函数的作用为 遍历容器,改变容器内所有T类型控件的文字颜色

/// <summary>
/// 遍历fatherControl内所有T类型控件,改变字体颜色
/// </summary>
/// <typeparam name="T">要改变字体颜色的类型</typeparam>
/// <param name="fatherControl">要遍历的控件</param>
/// <param name="Col">改变的颜色</param>
private void GetControls1<T>(Control fatherControl, Color Col) where T : Control
{
    Control.ControlCollection sonControls = fatherControl.Controls;
    //遍历所有控件  
    foreach (Control control in sonControls)
    {
        if (control is T)
        {
            (control as T).ForeColor = Col;
        }
        if (control.Controls != null)
        {
            GetControls1<T>(control, Col);
        }
    }
}
where T : Control 为泛型约束,传入的类型T仅为Control 或它的子类
### C# 构造函数参数传递 在 C# 中,类或方法可以通过 `where` 关键字施加约束条件,其中一种常见的约束是 `new()` 约束。这表示类参数必须具有无参数的公共构造函数[^4]。然而,在某些情况下,我们需要向类的实例化过程中传递参数给其构造函数。虽然直接通过本身无法支持带参数的构造函数实例化,但我们可以通过其他方式间接实现这一需求。 以下是几种常见的方式: #### 方法一:使用工厂模式 通过定义一个静态方法作为工厂方法,可以在创建对象时传递必要的参数并完成初始化操作。 ```csharp public class GenericFactory<T> where T : new() { public static T CreateInstance(params object[] constructorArgs) { var constructors = typeof(T).GetConstructors(); foreach (var ctor in constructors) { try { return (T)ctor.Invoke(constructorArgs); } catch { /* Ignore mismatched arguments */ } } throw new InvalidOperationException("No matching constructor found."); } } // 调用示例 class ExampleClass { public string Name { get; } public ExampleClass(string name) { this.Name = name; } } static void Main(string[] args) { var instance = GenericFactory<ExampleClass>.CreateInstance(new object[] { "TestName" }); Console.WriteLine(instance.Name); // 输出 TestName } ``` 这种方法利用反射机制找到目标类的合适构造函数,并调用它来创建新实例[^1]。 #### 方法二:依赖注入容器 现代应用程序通常采用依赖注入框架管理复杂对象图的构建过程。在这种设计中,您可以配置 DI 容器以解析特定类的构造函数参数。 ```csharp using Microsoft.Extensions.DependencyInjection; IServiceCollection services = new ServiceCollection(); services.AddTransient((serviceProvider) => { return new ExampleClass("InjectedParameter"); }); IServiceProvider serviceProvider = services.BuildServiceProvider(); ExampleClass exampleObject = serviceProvider.GetService<ExampleClass>(); Console.WriteLine(exampleObject.Name); // 输出 InjectedParameter ``` 这种方式不仅限于简单的字符串或其他基础类值,还可以处理复杂的依赖关系树[^3]。 #### 方法三:封装外部逻辑 另一种简单而有效的做法就是将构造所需的额外信息存储在一个辅助结构体或者类里,再把这个整体当作单一实体传进去。 ```csharp public abstract class BaseCreator<T> { protected readonly Func<object[], T> _creatorFunction; protected BaseCreator(Func<object[], T> creatorFunc) { _creatorFunction = creatorFunc ?? throw new ArgumentNullException(nameof(creatorFunc)); } public virtual T MakeNew(params object[] initParams) => _creatorFunction(initParams); } public sealed class SpecificTypeBuilder : BaseCreator<MyCustomType> { private const int DefaultAgeValueIfNotProvided = 20; internal SpecificTypeBuilder() : base(argsArray => ((string nameArg, int? ageOpt) = ( argCount >= 1 ? Convert.ToString(argsArray[0])! : throw new ArgumentException("Missing required 'name' argument"), argCount > 1 && argsArray[1] is not null ? Convert.ToInt32(argsArray[1]) : (int?)null)) ) => new MyCustomType(nameArg, ageOpt.HasValue ? ageOpt.Value : DefaultAgeValueIfNotProvided)) when (argsArray.Length == 0 || argsArray.All(a => a != null)) && !(argsArray.Any(argItem => argItem.GetType().IsValueType && Equals(argItem, default))) ) { } override public MyCustomType MakeNew(object firstParam, object secondOptionalParam=default!) { if(firstParam==null||!(firstParam is string validStrRepOfName)) throw new InvalidDataException($"Invalid input supplied:{nameof(validStrRepOfName)}"); return base.MakeNew(firstParam,secondOptionalParam); } } internal record struct MyCustomType(string FullName,int AgeAtCreation); // Usage Sample: SpecificTypeBuilder builderInst=new (); MyCustomType sampleRecord=builderInst.MakeNew("John Doe",35u); System.Console.Out.WriteLine($"{sampleRecord.FullName} was created at age {sampleRecord.AgeAtCreation}"); ``` 这里展示了如何借助 lambda 表达式简化内部工作流程的同时保持对外部使用者友好的 API 设计风格[^2]。 --- ### 总结 尽管标准语法不支持直接为受制于 `new()` 的提供有参构造器签名,但上述三种策略均能很好地解决这个问题。具体选择取决于项目的规模、团队偏好以及性能考量等因素。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值