考虑到通用方法,是否有可能在模板类型上设置约束以具有某些特定属性?
为了成功编译以下代码,例如
public static int[] DoSomething<T> (T[] Input)
{
int[] Output = new int[Input.Length];
for (int i = 0;i < Input.Length;i++)
Output[i] = (int)Input[i].PropertyA+(int)Input[i].PropertyB;
return Output;
}
模板类型需要实现PropertyA和PropertyB。 有可能以某种方式在模板类型上设置这样的约束吗?
修改: 并且还要求PropertyA和PropertyB是数字类型,因此可以将它们键入int。
感谢。
答案 0 :(得分:5)
唯一的可能性是将T定义为从一些众所周知的基类派生的类型或实现众所周知的接口:
public interface IWellKnown
{
int PropertyA { get; }
int PropertyB { get; }
}
您的任何方法都是:
public static int[] DoSomething<T> (T[] Input) where T : IWellKnown
{
int[] Output = new int[Input.Length];
for (int i = 0;i < Input.Length;i++)
Output[i] = Input[i].PropertyA+Input[i].PropertyB;
return Output;
}
编辑:
创建使用任何数字类型但只使用数字类型的泛型方法是不可能的,因为.NET没有像Number
这样的基类型。因此,您不能仅将通用类型限制为数字。所有数字类型都是值类型,因此您可以执行以下操作:
public interface IWellKnown<TData> where TData : struct
{
TData PropertyA { get; }
TData PropertyB { get; }
}
但在这种情况下,您的界面将接受任何值类型 - 任何自定义结构,char,bool等。
答案 1 :(得分:0)
不可能创造这样的限制。您应该在运行时检查输入并抛出一个有用的异常错误消息。
但你可以这样做:
public interface IWellKnown
{
int PropertyA { get; }
int PropertyB { get; }
}
public abstract class WellKnownBase<T> : IWellKnown
{
IWellKnown.PropertyA { get { return Convert(this.PropertyA); } }
IWellKnown.PropertyB { get { return Convert(this.PropertyB); } }
public T PropertyA { get; }
public T PropertyA { get; }
protected virtual int Convert(T input) { return (int)input; }
}
使用这样的基类引导实现具体版本的基类提供一种转换为int
的方法。显式接口实现提供对int
类型访问器的访问,而“真实”类仍提供原始类型。
public class WellKnownFloat : WellKnownBase<Float> {}
会为你提供一个浮动类。如果类型不能转换为int,则可以提供自定义转换器:
public class WellKnownTimeSpan : WellKnownBase<TimeSpan>
{
protected override int Convert(TimeSpan input)
{
return (int)input.TotalMilliseconds;
}
}
顺便说一下,使用linq并将需求添加到界面中,您可以将函数重写为input.Select(x => x.PropertyA + x.PropertyB)).ToArray()
。
PS:请使用VisualStudio检查代码,我只是在没有编译器支持的情况下编写代码;)可能存在小的编译时错误。