Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.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
.net 有没有一种优雅的方法可以用参数实例化变量类型?_.net_Generics_Instantiation - Fatal编程技术网

.net 有没有一种优雅的方法可以用参数实例化变量类型?

.net 有没有一种优雅的方法可以用参数实例化变量类型?,.net,generics,instantiation,.net,Generics,Instantiation,这是不合法的: public class MyBaseClass { public MyBaseClass() {} public MyBaseClass(object arg) {} } public void ThisIsANoNo<T>() where T : MyBaseClass { T foo = new T("whoops!"); } 公共类MyBaseClass { 公共MyBaseClass(){} 公共MyBaseClass(对象arg){} }

这是不合法的:

public class MyBaseClass
{
  public MyBaseClass() {}
  public MyBaseClass(object arg) {}
}


public void ThisIsANoNo<T>() where T : MyBaseClass
{
  T foo = new T("whoops!");
}
公共类MyBaseClass
{
公共MyBaseClass(){}
公共MyBaseClass(对象arg){}
}
public void thisisano()其中T:MyBaseClass
{
T foo=新的T(“哎哟!”);
}
为此,您必须对T的类型对象进行一些反射,或者必须使用Activator.CreateInstance。这两个都很讨厌。有更好的办法吗

where T : MyBaseClass, new()

仅适用于无参数公共构造函数。除此之外,回到activator.CreateInstance(其实没那么糟糕)。

不。如果不传入参数,则可以将类型param约束为需要无参数构造函数。但是,如果你需要传递参数,你就不走运了。

我可以看出这是行不通的

但是什么阻止了你这么做

public void ThisIsANoNo<T>() where T : MyBaseClass
{
  MyBaseClass foo = new MyBaseClass("whoops!");
}
public void thisisanno(),其中T:MyBaseClass
{
MyBaseClass foo=新的MyBaseClass(“哎哟!”);
}
因为所有东西都将从MyBaseClass继承,所以它们都将是MyBaseClass,对吗

我试过了,效果很好

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            ThisIsANoNo<MyClass>();
            ThisIsANoNo<MyBaseClass>();
        }

        public class MyBaseClass
        {
            public MyBaseClass() { }
            public MyBaseClass(object arg) { }
        }

        public class MyClass :MyBaseClass
        {
            public MyClass() { }
            public MyClass(object arg, Object arg2) { }
        }

        public static void ThisIsANoNo<T>() where T : MyBaseClass
        {
            MyBaseClass foo = new MyBaseClass("whoops!");
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
命名空间控制台应用程序1
{
班级计划
{
静态void Main(字符串[]参数)
{
Thisisano();
Thisisano();
}
公共类MyBaseClass
{
公共MyBaseClass(){}
公共MyBaseClass(对象arg){}
}
公共类MyClass:MyBaseClass
{
公共MyClass(){}
公共MyClass(对象arg,对象arg2){}
}
公共静态void thisisano(),其中T:MyBaseClass
{
MyBaseClass foo=新的MyBaseClass(“哎哟!”);
}
}
}

您不能将t约束为具有除空构造函数以外的特定构造函数签名,但可以将t约束为具有所需签名的工厂方法:

public abstract class MyBaseClass
{
    protected MyBaseClass() {}
    protected abstract MyBaseClass CreateFromObject(object arg);
}

public void ThisWorksButIsntGreat<T>() where T : MyBaseClass, new()
{
    T foo = new T().CreateFromObject("whoopee!") as T;
}
公共抽象类MyBaseClass
{
受保护的MyBaseClass(){}
受保护的抽象MyBaseClass CreateFromObject(对象arg);
}
public void thisWorksbutitgreat(),其中T:MyBaseClass,new()
{
T foo=new T().CreateFromObject(“哇哇!”)作为T;
}

但是,我建议在这个场景中使用不同的创建模式,例如抽象工厂。

如果派生类只有一个构造函数,并且构造函数只有两个参数,会发生什么情况?这个方法永远不会返回T类型的对象,只返回MyBaseClass类型的对象。它是一个空值,不会返回任何内容。强制转换可以解决这个问题。T是MyBaseClass的扩展。您可以新建MyBaseClass的实例,但不能将其“上转换”为T,因为它不是T。此外,ThisisAnno实现虽然具有泛型签名,但不会新建类型变量的实例。