在C#编程语言中,泛型类提供了一种强大的机制来编写类型安全且可重用的代码。通过使用泛型,可以创建能够处理多种数据类型的类,而无需牺牲类型检查或性能。本文将深入探讨如何在泛型类中构建逻辑,以及编译器如何理解泛型类中的类型参数。
在C#中,编译器对泛型类中的类型参数了解有限。考虑以下泛型类示例:
public class GenericDemo
{
public void Foo(T Value)
{
// 编译器对Value的了解是什么?
}
}
编译器唯一确定的是,Value参数的类型是Object。任何创建此泛型类实例的人都可以传递任何类型作为类型参数。所有可能性之间的唯一共同点是它们必须是Object类型。这意味着在Foo方法内部,只能对Value参数执行可以对对象执行的操作。
可以通过添加约束来告诉编译器更多关于类型参数的信息。以下是.NET文档中关于类型参数约束的参考:
添加约束后,泛型类可以如下所示:
public class GenericDemo where T : IComparable
{
public T GetBiggerValue(T value1, T value2)
{
if (value1.CompareTo(value2) >= 0)
return value1;
return value2;
}
}
这里,“where T : IComparable
让快速看一下其他约束类型。
无参数构造函数约束:
public class HasParameterlessConstructor
{
public HasParameterlessConstructor() { }
}
public class DoesNotHaveParameterlessConstructor
{
public DoesNotHaveParameterlessConstructor(int parameter1, string paramter2) { }
}
public class GenericDemo where T : new()
{
public static T CreateNewInstance()
{
var newInstance = new T();
return newInstance;
}
}
上述示例中的约束“where T : new()”告诉编译器类型T必须有无参数构造函数。
以下示例中的'class'约束告诉编译器T必须是一个引用类型:
public class GenericDemo where T : class, IComparable
{
public static T GetBiggerValue(T value1, T value2)
{
if (value1.CompareTo(value2) >= 0)
return value1;
return value2;
}
}
以下示例中的'struct'约束告诉编译器T必须是一个值类型:
public class GenericDemo where T : struct, IComparable
{
public static T GetBiggerValue(T value1, T value2)
{
if (value1.CompareTo(value2) >= 0)
return value1;
return value2;
}
}
让构建一个简单的泛型类示例,它使用约束并具有实际用途。这个示例允许将作业添加到集合中,然后根据优先级执行它们。
public interface IJob
{
int GetPriority();
void Execute();
}
public class JobRunner where T : IJob, IComparable
{
private List _jobList = new List();
private class JobComparer : IComparer
{
public int Compare(T x, T y)
{
return x.CompareTo(y);
}
}
public void AddJob(T job)
{
_jobList.Add(job);
}
public void ExecuteJobs()
{
var sortedByPriority = _jobList.OrderByDescending(x => x, new JobComparer());
foreach (var job in sortedByPriority)
{
job.Execute();
}
}
}
public class WriteToConsoleJob : IJob, IComparable
{
private int _priority;
private string _toWrite;
public WriteToConsoleJob(int priority, string toWrite)
{
_toWrite = toWrite;
_priority = priority;
}
public int GetPriority()
{
return _priority;
}
public void Execute()
{
Console.WriteLine(_toWrite);
}
public int CompareTo(IJob other)
{
return this.GetPriority().CompareTo(other.GetPriority());
}
}
这个泛型类可以像这样使用:
var jobRunner = new JobRunner();
var highPriorityJob = new WriteToConsoleJob(1000, "high priority job");
var lowPriorityJob = new WriteToConsoleJob(50, "low priority job");
var mediumPriorityJob = new WriteToConsoleJob(500, "medium priority job");
jobRunner.AddJob(lowPriorityJob);
jobRunner.AddJob(highPriorityJob);
jobRunner.AddJob(mediumPriorityJob);
jobRunner.ExecuteJobs();
控制台上的输出将是:
high priority job
medium priority job
low priority job
这行代码:
public class JobRunner where T : IJob, IComparable