5

方法有类型参数。为什么构造函数没有类型参数?

例子

我认为有几个(不是很多)例子会很有用。我目前的问题如下:

internal class ClassA
{
   private readonly Delegate _delegate;

   public ClassA<T>(Func<T> func)
   {
     _delegate = func;
   }
}

我的课一个Delegate就够了。但是要将其作为方法组传递,我需要将参数定义为Func<T>.

4

5 回答 5

2

他们只是没有包含该功能,可能是假设它不是很有用。

如果构造函数需要它,则整个类型可能都需要它。但在你不这样做的情况下,你可能仍然可以使用 Object 。

如果你不能......是的,我认为没有什么办法可以解决,抱歉。:\ 你可以使用反射,但当然会慢得离谱......或者你可以玩动态生成方法的技巧,这可能是值得的,具体取决于你的用例,但也可能很慢(它至少增加了 1额外的间接调用)。

于 2012-05-11T07:48:25.667 回答
2

因为构造函数是类的一部分,所以类型参数可能属于整个类型。

如果您在构造泛型类的实例时可以选择使用不同的类型参数,那么您实际上是在构造不同类型的类。我知道它与 C++ 中的模板类不同,但概念相似。

要解决您的特定问题,您可以使用“模板化”工厂方法。

于 2012-05-11T07:48:37.003 回答
2

After reading the C# specification it actually does make sense, but it can be confusing.

Each class has an associated instance type, and for a generic class declaration the instance type is formed by creating a constructed type from the type declaration, with each of the supplied type arguments being the corresponding type parameter.

class C<T>
{ 
}

C<T> is a constructed type, and an instance type will be created by the process of constructing the type using the type parameters.

C<String> c = new C<String>();

The compiler took the constructed type C<T>, and using the supplied type parameters an instance type of C<String> was created. Generics is only a compile time construct, everything is executed in the terms of closed constructed types at runtime.

Now let's take your question and put it to the test here.

class C
{
    public C<T>() 
    {
    }
}

This isn't possible, because you are trying to construct a type that doesn't exist.

C c = new C<String>();

What is the implicit or explicit conversion between C and C<String>? There is none. It doesn't even make sense.

Because C is a non-generic type in this example, the instance type is the class declaration itself. So how do you expect C<String> to construct C?

The proper declaration for what you want to do is this.

internal class Class<T> 
{
    private readonly Delegate _delegate;

    public Class(Func<T> function) 
    {
        _delegate = function;
    }
}

Here because we have a constructed type Class<T>, the proper instance type can be created by the compiler.

Func<String> function = new Func<String>(() => { return String.Empty; });
Class<String> c = new Class<String>(function);

If you tried to do it the way you want in your question.

Func<String> function = new Func<String>(() => { return String.Empty; });
Class c = new Class<String>(function);

The constructed type would be Class<String>, which is not the same as type C, and there is no implicit or explicit conversion from either one. If this was allowed by the compiler, C would be in some unknown and unusable state.

What you do need to know about constructed types, is this.

class C<T>
{
    public C<T>() 
    {
    }
}

While you cannot explicitly declare a generic constructor, it is valid but only as a closed type constructor at runtime.

C<String> c = new C<String>();

At compile time, the following constructor is created.

public C<String>() 
{
}

Which is why this is valid:

C<String> c = new C<String>(); // We just used the closed type constructor

If what you wanted was allowed, something like this could happen.

class C<T>
{
    public C<U>() 
    {
    }
}

// ???
C<String> c = new C<Int32>();

You can see the problems now that would arise if the construct was allowed. Hopefully this sheds some insight, the specification is rather long and there are many many many sections that cover generics, type parameters, constructed types, closed and open types, bound and unbound.

It can get very confusing, but its a good thing that this isn't allowed by the compiler rules.

于 2012-05-11T08:17:25.687 回答
1

You can pass in a delegate instead of a strongly typed Func<T>. You will not be able to know the type at compile time, but you wouldn't have that when you pass in the Func<T> either. When you want that you'd have to make the whole class generic.

class Program {
        static void Main(string[] args) {
            Func<int> i = () => 10;
            var a1 = new ClassA(i);

            Func<string> s = () => "Hi there";
            var a2 = new ClassA(s);            
        }
    }

    internal class ClassA {
        private readonly Delegate _delegate;

        public ClassA(Delegate func) { // just pass in a delegate instead of Func<T>
            _delegate = func;
        }
    }
于 2012-05-11T08:14:13.433 回答
0

因为你可以通过将你的类声明为泛型来实现

internal class ClassA<T>
{
 private readonly Delegate _delegate;

  public ClassA(Func<T> func)
  {
    _delegate = func;
  }
}

then you will have implicitly a generic construct

于 2012-05-11T08:08:57.767 回答