有没有办法指定哪里T:new()限制,但内部构造函数?

时间:2012-05-11 10:30:12

标签: c# .net generics restriction

我已经创建了一个需要实例化其实现类型的泛型类,因此实现类型必须具有可访问参数而不是构造函数。看起来new()限制可以完成这项工作,但它强制执行类型,以便在我将其置于内部时具有公共构造函数(但可以访问,因为两者都在同一个程序集中)。

  1. 是否有理由强迫它公开而不是“可访问”?
  2. 有办法做我需要的吗?
  3. 提前致谢。

    编辑:这样做的原因是我有一个必须通过Singleton使用的类X. Singleton类是一个泛型类,我想让内部的X类构造函数避免外部用户以错误的方式访问对象(调用构造函数)。

3 个答案:

答案 0 :(得分:6)

规范绑定和未绑定类型的第4.4.3节中概述的C#语言不允许这样做。

  

如果约束是构造函数约束new(),则类型A不能是abstract,并且必须具有公共无参数构造函数。如果满足下列条件之一,则满足。

     
      
  • A是一种值类型,因为所有值类型都有一个公共默认构造函数
  •   
  • A是具有cosntructor约束的类型参数
  •   
  • A是具有值类型约束
  • 的类型参数   
  • A是一个不是abstract的类,包含一个没有参数的显式声明的public构造函数
  •   
  • A不是abstract,并且有默认构造函数。
  •   

如果不满足其中任何一个条件,则编译错误。如果您发现自己的类型是公共的但只有内部构造函数,那么它们很可能实际上应该是具有公共构造函数的内部类型。

我建议将internal及其构造函数的类型访问器更改为public,并使其无参数。然后,您的public无参数构造函数可以调用非参数privateinternal构造函数来执行任何其他初始化工作。

internal class C<T> where : T new()
{
    public C() : this(new T()) {
    }

    private C(T t) {
        // Do additional initialization
    }
}

请注意,模式是有限的,但没有什么能阻止您使用private方法。

internal class C<T> where T : new() {
    public C() {
        T t = new T();
        InitializeClass(t);
    }

    private void InitializeClass(T t) {
        throw new NotImplementedException();
    }
}   

根据您的更新,这是一个公共单身模式的小例子。

public class Singleton<T> where T : new()
{
    public static Singleton<T> Current {
        get;
        private set;
    }

    internal Singleton() : this(new T()) {
    }

    private Singleton(T t) {
        Current = this;
        // Do whatever you need to with T
    }        

    public String Name {
        get;
        set;
    }
}

用法

// Somewhere in your internal assembly
Singleton<String> singleton = new Singleton<String>();

// In an external assembly
Singleton.Current.Name = "SoMoS";

您甚至不需要以这种方式使用构造函数,您可以轻松地执行简单的操作。

public class Singleton<T> where T : new()
{
    public static Singleton<T> Current {
        get;
        private set;
    }

    internal Singleton() {
        T t = new T();
        // Do stuff with T
    }

    public String Name {
        get;
        set;
    }
}
如果无法根据您的要求进行设计,那么

Generics 可能不是的方法。泛型只能做很多事情并且不能解决所有问题。有工厂模式,注射等等。

答案 1 :(得分:2)

  

是否有理由强迫它公开而不是“可访问”?

术语可访问非常上下文敏感,泛型不是,通过体系结构。 在您的特定情况下,internal可以访问,但泛型是针对通用解决方案的。

  

有办法做我需要的吗?

基于第一点,不,这是不可能的,也不是我所知道的。

答案 2 :(得分:1)

泛型用于通用解决方案,因此如果您使用“新”约束,则您的解决方案必须与实现公共ctor的每个类一起使用。

如果要为特定类的类实现通用解决方案,可以定义实现此类内部构造函数的抽象基类。为此抽象基类实现通用解决方案并使用

* 其中T:MyBaseClassWithInternalCtor *

作为约束。