7

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

  1. 是否有理由强迫它公开而不是“可访问”?
  2. 有没有办法做我需要的?

提前致谢。

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

4

3 回答 3

6

如规范Bound and Unbound Types的第 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;
    }
}

如果你不能设计它来满足你的要求,泛型可能不是要走的路。泛型只能做这么多,并不能解决所有问题。有工厂模式,注入等。

于 2012-05-11T11:22:16.550 回答
2

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

术语可访问是非常上下文敏感的,泛型不是,由架构。在您的特定情况下internal可以访问,但泛型是为通用解决方案制作的。

有没有办法做我需要的?

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

于 2012-05-11T10:34:26.457 回答
1

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

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

* 其中 T : MyBaseClassWithInternalCtor *

作为约束。

于 2012-05-11T11:12:36.140 回答