C# 可为空<;T>;作为参数

C# 可为空<;T>;作为参数,c#,generics,types,abstract,nullable,C#,Generics,Types,Abstract,Nullable,我一直试图为一个personnal库项目处理泛型类型和抽象,但我面临一个问题。 我发现这有点像我想做的,但我想把它推进一步。因为我想用泛型参数将我的函数约束为只有少数类型 比如: publicstatict-Read(T?min,T?max),其中T:int,float,double,任何我想要的 { } 我知道这样做是不可能的,但我正试图找到一些解决办法来实现类似的目标 我试图设置为使用:T? 但我得到一条消息,说T不能为null,不能用作参数。 如您所见: 其中F:ConsoleReadT

我一直试图为一个personnal库项目处理泛型类型和抽象,但我面临一个问题。 我发现这有点像我想做的,但我想把它推进一步。因为我想用泛型参数将我的函数约束为只有少数类型 比如:

publicstatict-Read(T?min,T?max),其中T:int,float,double,任何我想要的
{
}
我知道这样做是不可能的,但我正试图找到一些解决办法来实现类似的目标

我试图设置为使用:
T?
但我得到一条消息,说T不能为null,不能用作参数。 如您所见:

其中F:ConsoleReadType
我基本上只允许运行继承的类

public abstract class ConsoleReadType<T>
{
    public abstract T Read();
    public abstract T Read(T? min, T? max);
    public virtual F ReadUntilCorrect<F>(Func<F> FunctionToRun, string message = "") /*where F : ConsoleReadType<T>*/
    {
        while (true)
        {
            try
            {
                return FunctionToRun();
            }
            catch (ConsoleInputException)
            {
                if (!string.IsNullOrEmpty(message))
                    ConsoleWrite.Error(message);
            }
        }
    }
}

public class ConsoleReadDouble : ConsoleReadType<double>
{
    public override double Read()
    {
        if (!double.TryParse(Console.ReadLine().Replace(".", ","), out double ret))
        {
            throw new ConsoleInputException();
        }
        return ret;
    }
    public override double Read(double? min, double? max)
    {
        if (!double.TryParse(Console.ReadLine().Replace(".", ","), out double ret))
        {
            throw new ConsoleInputException("invalid input format");
        }
        if (min.HasValue && ret < min || max.HasValue && ret > max)
        {
            throw new ConsoleInputException("input value should be between: " + min + " and " + max);
        }
        return ret;
    }
}
公共抽象类ConsoleReadType
{
公共摘要不可读();
公开摘要T-Read(T?min,T?max);
公共虚拟F ReadUntilCorrect(Func functionorun,string message=“”)/*其中F:ConsoleReadType*/
{
while(true)
{
尝试
{
返回函数torun();
}
捕获(控制台输入异常)
{
如果(!string.IsNullOrEmpty(消息))
控制台写入错误(消息);
}
}
}
}
公共类CONSOLEREADDUBLE:ConsoleReadType
{
公共重写双读()
{
如果(!double.TryParse(Console.ReadLine().Replace(“.”,“,”),out double ret))
{
抛出新的ConsoleInputException();
}
返回ret;
}
公共覆盖双读(双最小值、双最大值)
{
如果(!double.TryParse(Console.ReadLine().Replace(“.”,“,”),out double ret))
{
抛出新的ConsoleInputException(“无效输入格式”);
}
如果(最小HasValue&&retmax)
{
抛出新的ConsoleInputException(“输入值应介于“+min+”和“+max”之间);
}
返回ret;
}
}
因此,主要问题是:
1.有没有一种方法可以抽象地设置可为null的T变量,或者有没有更好的方法来实现我的目标?
2.我可以只允许某些带有where语句的函数吗?
3.有没有一种方法可以使这些类最终成为静态的,而不必实例化它们就可以用作助手?
4.我也对你能给我的任何关于我的代码的建议感兴趣


非常感谢。

您可以使用
struct
其中T:struct
)将泛型类型限制为值类型。然后可以使用
Nullable
/
T?

public abstract class ConsoleReadType<T> where T: struct
{
    public abstract T Read();
    public abstract T Read(T? min, T? max);
}
然后可以使用如下具体类:

class Program
{
    static void Main(string[] args)
    {
        double d = ConsoleReadDouble.ReadUntilCorrect("Please enter a valid number");

    }
}

您可以使用
struct
其中T:struct
)将泛型类型限制为值类型。然后可以使用
Nullable
/
T?

public abstract class ConsoleReadType<T> where T: struct
{
    public abstract T Read();
    public abstract T Read(T? min, T? max);
}
然后可以使用如下具体类:

class Program
{
    static void Main(string[] args)
    {
        double d = ConsoleReadDouble.ReadUntilCorrect("Please enter a valid number");

    }
}

你可以这样做:

// add where T: struct so that only structs (int, double, etc) can be used
// allows you to use T? 
public abstract class ConsoleReadType<T> where T: struct
{
    public abstract T Read();
    public abstract T Read(T? min, T? max);
    public virtual T ReadUntilCorrect(Func<T> FunctionToRun, string message = "")
    {
        while (true)
        {
            try
            {
                return FunctionToRun();
            }
            catch (ConsoleInputException)
            {
                if (!string.IsNullOrEmpty(message))
                    ConsoleWrite.Error(message);
            }
        }
    }
}

你可以这样做:

// add where T: struct so that only structs (int, double, etc) can be used
// allows you to use T? 
public abstract class ConsoleReadType<T> where T: struct
{
    public abstract T Read();
    public abstract T Read(T? min, T? max);
    public virtual T ReadUntilCorrect(Func<T> FunctionToRun, string message = "")
    {
        while (true)
        {
            try
            {
                return FunctionToRun();
            }
            catch (ConsoleInputException)
            {
                if (!string.IsNullOrEmpty(message))
                    ConsoleWrite.Error(message);
            }
        }
    }
}

问题还不清楚。您为什么希望
ReadUntilCorrect
使用不同的泛型参数?您到底想用它做什么。为什么不在类中调用Read方法呢?我相信您希望在ConsoleReadType声明中将
T
约束到
struct
。double不是struct thoYes,double是一个struct,以满足泛型参数类型约束。约束“struct”意味着该类型必须是值类型。@kenny double是一个结构,就像其他所有数值原语类型一样,这个问题不清楚。您为什么希望
ReadUntilCorrect
使用不同的泛型参数?您到底想用它做什么。为什么不在类中调用Read方法呢?我相信您希望在ConsoleReadType声明中将
T
约束到
struct
。double不是struct thoYes,double是一个struct,以满足泛型参数类型约束。约束“struct”表示该类型必须是值类型。@kenny double是一个struct,与其他任何数值基元类型一样