Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/260.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么构造函数中不允许使用类型参数?_C# - Fatal编程技术网

C# 为什么构造函数中不允许使用类型参数?

C# 为什么构造函数中不允许使用类型参数?,c#,C#,方法有类型参数。为什么构造函数没有类型参数 例子 我认为有几个(不是很多)例子是有用的。我目前的问题如下: internal class ClassA { private readonly Delegate _delegate; public ClassA<T>(Func<T> func) { _delegate = func; } } 内部类ClassA { 私有只读委托_委托; 公共A类(Func Func) { _委托=函数;

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

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

internal class ClassA
{
   private readonly Delegate _delegate;

   public ClassA<T>(Func<T> func)
   {
     _delegate = func;
   }
}
内部类ClassA
{
私有只读委托_委托;
公共A类(Func Func)
{
_委托=函数;
}
}

一个
代表
对我的班级来说就足够了。但要将其作为方法组传递,我需要将参数定义为
Func

它们只是不包含该特性,可能是因为假设它不会非常有用

如果构造函数需要它,那么整个类型可能都需要它。但在不使用对象的情况下,您可能仍然可以使用对象


如果你不能。。。是的,我觉得没什么办法,对不起你可以使用反射,但那当然会慢得可笑。。。或者,您可以动态生成方法,这可能是值得的,这取决于您的用例,但也可能很慢(它至少添加了一个额外的间接调用)。

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

如果在构造泛型类的实例时可以选择不同的类型参数,那么实际上就是在构造不同类型的类。我知道它与C++中的模板类不一样,但是概念是相似的。
为了解决您的特定问题,您可以使用“模板化”工厂方法。

因为您可以通过将类声明为泛型来实现这一点

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

  public ClassA(Func<T> func)
  {
    _delegate = func;
  }
}
内部类ClassA
{
私有只读委托_委托;
公共A类(Func Func)
{
_委托=函数;
}
}

然后您将隐式地拥有一个泛型构造

,您可以传入一个委托,而不是一个强类型Func。您将无法在编译时知道该类型,但在传入Func时也无法知道该类型。如果需要,则必须使整个类成为泛型

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;
        }
    }
类程序{
静态void Main(字符串[]参数){
Func i=()=>10;
var a1=新的A类(i);
Func s=()=>“你好”;
var a2=新的A类;
}
}
内部A类{
私有只读委托_委托;
public ClassA(Delegate func){//只需传入一个委托而不是func
_委托=函数;
}
}
在阅读了C#规范之后,它实际上是有意义的,但它可能会令人困惑

每个类都有一个关联的实例类型,对于泛型类声明,实例类型是通过从类型声明创建构造的类型形成的,提供的每个类型参数都是相应的类型参数

class C<T>
{ 
}
这里因为我们有一个构造的类型
,所以编译器可以创建适当的实例类型

Func<String> function = new Func<String>(() => { return String.Empty; });
Class<String> c = new Class<String>(function);
虽然不能显式声明泛型构造函数,但它在运行时仅作为封闭类型构造函数有效

C<String> c = new C<String>();
C=newc();
在编译时,将创建以下构造函数

public C<String>() 
{
}
public()
{
}
这就是为什么这是有效的:

C<String> c = new C<String>(); // We just used the closed type constructor
C=newc();//我们刚刚使用了封闭类型构造函数
如果你想要的被允许,这样的事情可能会发生

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

// ???
C<String> c = new C<Int32>();
C类
{
公共C()
{
}
}
// ???
C=新的C();
您现在可以看到,如果允许构造,将出现的问题。希望这能提供一些见解,规范相当长,有许多章节涵盖泛型、类型参数、构造类型、封闭和开放类型、绑定和非绑定


这可能会让人非常困惑,但编译器规则不允许这样做,这是一件好事。

可能重复@FlorianGreinacher:这些问题不是同一个问题。只是一个小问题,不值得一个完整的答案。。。
var x=new MyClass(5)
会调用非泛型类
MyClass
上的
MyClass(T参数)
构造函数,还是泛型类
MyClass
上的
MyClass(T参数)
构造函数?@Rawling说得好。我认为你的评论(事实上)值得作为一个答案。我觉得在@EricLippert注意到这一点之前,这不会得到答案,即使这样,它也只是标准的“这是一个如此不同寻常的案例,我们觉得我们的努力应该花在其他地方。”-样式一。如果我只想为构造函数体添加类型参数,我不想将此类型参数添加到整个类中。构造函数上的类型参数如何不影响类的实例?@gjvdkamp我现在为我的问题添加了一个示例。是的,这是可能的。但这里不可能将func作为方法组传递。我喜欢将函数作为方法组传递:-)好的。。为什么呢?你想要达到什么效果?我更喜欢方法组语法
newclassa(Function1)
而不是对应的
newclassa((Func)Function1)
。当然,这是一个明显的例子。在第一个类中,错误仍然在第一个“构造函数”上,而不是第二个。而使用
隐式
显式
转换不会有任何区别。您不能显式声明它,但
C()
是编译器生成的有效构造函数,因此声明性语法为
C=new C()和它的转换确实会有所不同。@DavidAnderson感谢您对内部结构的印象。我是否理解这个特性有两个缺点:a)由.NET和C#团队进行大量工作,b)由于当前构造函数语法的缺乏?C#是一种类型安全语言,这对langauge来说是一个非常不安全的特性,因此它永远不会被包括在内。例如,在我的上一个示例中,使用
String
Int32
会破坏类型安全性。我非常忧郁
Func<String> function = new Func<String>(() => { return String.Empty; });
Class c = new Class<String>(function);
class C<T>
{
    public C<T>() 
    {
    }
}
C<String> c = new C<String>();
public C<String>() 
{
}
C<String> c = new C<String>(); // We just used the closed type constructor
class C<T>
{
    public C<U>() 
    {
    }
}

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