我可以定义一个只接受基本类型的方法吗?

时间:2014-06-11 18:20:47

标签: c# generics primitive-types type-constraints

我想创建一个只接受基本类型的构造函数,我该怎么做?

就像这个例子:

public Test(PrimitiveType type)
{

}

我需要在构造函数中执行它并且它是可选的,所以我想创建一个无参数构造函数和带参数的构造函数。

4 个答案:

答案 0 :(得分:6)

根据您想要实现的目标,您可能希望查看所谓的"可转换类型",例如实现IConvertible接口的类型如下:

  • Boolean
  • SByte
  • Byte
  • Int16
  • UInt16
  • Int32
  • UInt32
  • Int64
  • UInt64
  • Single
  • Double
  • Decimal
  • DateTime
  • Char
  • String

因此,正如您所看到的,这几乎涵盖了您希望用原始类型实现的目标。

所以,通过写这样的方法

public void Test(IConvertible primitive)
{
   if (primitive is Double) ....
   if (primitive is String) ....
}

您将输入类型限制为以下(无结构等)。

或者,您也可以将其实现为通用方法:

public void Test<T>(T primitive) where T : IConvertible
{
   if (primitive is Double) ....
   if (primitive is String) ....
}

由于您设置了此约束,因此您始终可以将类型转换为1,例如:

public void Test<T>(T primitive) where T : IConvertible
{
   var myval = Convert.ToDecimal(primitive);
   ....
}

答案 1 :(得分:3)

单个重载¹无法做到这一点(当然,你可以为每个基本类型编写重载)。你可以让它只接受值类型,但它会接受任何struct,而不仅仅是原始类型。


¹好吧,在编译时不可能强制执行它,但你可以在运行时检查类型并抛出例外当然......

答案 2 :(得分:1)

编辑:我在上一个回答中完全错了。请参阅以下

类型类实际上具有IsPrimitive属性。这将允许您检查类数据是否是原始数据。

对于您需要采用多种可接受类型的任何内容,您需要使其成为通用的,严格限制运行时的某些选项。

public void SomeMethod<T>(T obj)
{
    if(typeof(T).IsPrimitive == false) throw new ArgumentException("obj");
}

更新:如果这是构造函数,则可以接受任何对象类型。否则,您必须使您的类对该参数具有通用性

// Constructor for SomeClass
public SomeClass(object obj)
{
    if(obj.GetType().IsPrimitive == false) throw new ArgumentException("obj");
}

答案 3 :(得分:1)

我给出了一个非常类似的解决方案before,但是使用模板可以生成多个重载,这些重载使用您想要的不同类型(在编译时)。

<#@ template language="C#" #>
<#@ output extension=".cs" #>
<#@ import namespace="NamespaceProofOfConcept" #>
<#@ assembly name="$(TargetPath)" #>


<# Type[] types = new[] {
    typeof(byte), typeof(short), typeof(int),
    typeof(long), typeof(float), typeof(double),
    typeof(bool), typeof(DateTime), typeof(char),
    typeof(string)
    };
#>

using System;
namespace NamespaceProofOfConcept {
public partial class Test {
<# foreach (var type in types) { 
#>
    public Test(<#= type.Name #> value) {
        doConstructorStuff(value);
    }
<#
} #>

    private void doConstructorStuff(object o){

    }
} 
}

这将生成以下类:

使用System;

namespace NamespaceProofOfConcept {
    public partial class Test {
        public Test(Byte value) {
            doConstructorStuff(value);
        }
        public Test(Int16 value) {
            doConstructorStuff(value);
        }
        public Test(Int32 value) {
            doConstructorStuff(value);
        }
        public Test(Int64 value) {
            doConstructorStuff(value);
        }
        public Test(Single value) {
            doConstructorStuff(value);
        }
        public Test(Double value) {
            doConstructorStuff(value);
        }
        public Test(Boolean value) {
            doConstructorStuff(value);
        }
        public Test(DateTime value) {
            doConstructorStuff(value);
        }
        public Test(Char value) {
            doConstructorStuff(value);
        }
        public Test(String value) {
            doConstructorStuff(value);
        }

        private void doConstructorStuff(object o){

        }
    } 
}

现在,您只能使用您定义的类型(基本上是VB.NET基元类型)调用此构造函数。

您可以通过创建自己的定义行为的分部类来为此添加功能:

namespace NamespaceProofOfConcept
{
    public partial class Test
    {
        public void DoAThing()
        {
            System.Console.WriteLine("custom method!");
        }
    }
} 

您可以使用以下代码测试它(输出&#34;自定义方法!&#34;):

static void Main(string[] args)
{
    Test obj = new Test(true);
    obj.DoAThing();
    Console.ReadKey();
}

如果您想要更多&#34; security&#34;,您可以在T4模板中将无参数构造函数定义为私有,因此除非修改模板,否则无法添加它。