C#:如何声明和使用具有不同类型的泛型类列表?

C#:如何声明和使用具有不同类型的泛型类列表?,c#,.net,generics,list,C#,.net,Generics,List,具有以下泛型类,将包含字符串、int、float、long作为类型: public class MyData<T> { private T _data; public MyData (T value) { _data = value; } public T Data { get { return _data; } } } 其中SomeMethod()声明如下: public void SomeMethod (string

具有以下泛型类,将包含字符串、int、float、long作为类型:

public class MyData<T>
{
    private T _data;

    public MyData (T value)
    {
        _data = value;
    }

    public T Data { get { return _data; } }
}
其中
SomeMethod()
声明如下:

public void SomeMethod (string value);
public void SomeMethod (int value);
public void SomeMethod (float value);

更新:

SomeMethod()
来自我无法控制的另一层类,并且
SomeMethod(对象)
不存在


然而,我似乎找不到让编译器满意的方法

有什么建议吗

谢谢。

从非泛型的
MyData
类继承
MyData
,并列出该类

这样,您就无法自动解决过载问题。你必须手动操作

abstract class MyData { 
   protected abstract object GetData();
   protected abstract Type GetDataType(); 
   public object Data {
      get { return GetData(); } 
   }
   public Type DataType {
      get { return GetDataType(); } 
   }
}

class MyData<T> : MyData { 
   protected override object GetData() { return Data; }
   protected override Type GetDataType() { return typeof(T); }
   public new T Data {
     get { ... }
   }
}
抽象类MyData{
受保护的抽象对象GetData();
受保护的抽象类型GetDataType();
公共对象数据{
获取{return GetData();}
}
公共类型数据类型{
获取{return GetDataType();}
}
}
类MyData:MyData{
受保护的重写对象GetData(){return Data;}
受保护的重写类型GetDataType(){return typeof(T);}
公共新T数据{
获取{…}
}
}

在这种情况下,您需要
MyData
,因为这是这些类型唯一的共同点。

泛型允许您在创建列表时为整个列表指定一种类型,例如,存储int的列表将这样创建

var myData = new MyData<int>();
var myData=new myData();
如果要在同一个泛型列表中存储多个类型,可以为这些类型指定公共基类型或接口。不幸的是,在您的情况下,要存储的类型的唯一公共基类型是object

var myData = new MyData<object>();
var myData=new myData();

但是您可以使用非通用列表来存储对象。

只需使用ArrayList,而不必考虑
MyData
类型

ArrayList myStuff = getStuff();
float x = myStuff.OfType<float>().First();
SomeMethod(x);
string s = myStuff.OfType<string>().First();
SomeMethod(s);
ArrayList myStuff=getStuff();
float x=myStuff.OfType().First();
方法(x);
字符串s=myStuff.OfType().First();
某些方法;

MyData
的问题在于,您希望编译器检查一个只有在运行时才知道的类型。编译器会检查编译时已知的类型。

您不能按自己的方式执行

初始化泛型类的实例时,它将绑定到特定类型。由于您希望在列表中保留不同类型的对象,因此必须创建一个绑定到最小公分母的实例—在您的示例中,它是对象

但是,这意味着Data属性现在将返回object类型的对象。编译器无法在编译时推断实际的数据类型,因此可以选择适当的
SomeMethod
重载

您必须提供一个重载
SomeMethod
,将对象作为参数,或者删除在集合中保存不同类型的要求


或者您可以使用标准的
IEnumerable
集合(如数组),并使用
of type
扩展方法获取特定类型集合的子集。

不久前建议使用通配符。关闭为“不会修复”:(

我认为您遇到的问题是,您正试图创建一个泛型类型,然后创建该泛型类型的列表。您可以通过将您试图支持的数据类型外包(例如作为IData元素),然后使用IData约束创建MyData泛型。downsid要做到这一点,您必须创建自己的数据类型来表示您正在使用的所有基本数据类型(string、int、float、long)

public class MyData<T, C>
    where T : IData<C>
{
    public T Data { get; private set; }

    public MyData (T value)
    {
         Data = value;
    }
}

public interface IData<T>
{
    T Data { get; set; }
    void SomeMethod();
}

//you'll need one of these for each data type you wish to support
public class MyString: IData<string>
{
   public MyString(String value)
   {
       Data = value;
   }

   public void SomeMethod()
   {
       //code here that uses _data...
       Console.WriteLine(Data);
   }

   public string Data { get; set; }
}

您可以为
SomeMethod
创建泛型包装,并检查泛型参数的类型,然后委托给相应的方法

public void SomeMethod<T>(T value)
{
    Type type = typeof(T);

    if (type == typeof(int))
    {
        SomeMethod((int) (object) value); // sadly we must box it...
    }
    else if (type == typeof(float))
    {
        SomeMethod((float) (object) value);
    }
    else if (type == typeof(string))
    {
        SomeMethod((string) (object) value);
    }
    else
    {
        throw new NotSupportedException(
            "SomeMethod is not supported for objects of type " + type);
    }
}
public方法(T值)
{
类型=类型(T);
if(type==typeof(int))
{
SomeMethod((int)(object)value);//遗憾的是,我们必须将其装箱。。。
}
else if(type==typeof(float))
{
SomeMethod((浮动)(对象)值);
}
else if(type==typeof(string))
{
SomeMethod((字符串)(对象)值);
}
其他的
{
抛出新的NotSupportedException(
类型为“+类型”的对象不支持“SomeMethod”;
}
}

委托人确实可以帮助简化这一过程,并且仍然可以保证事情的类型安全:

public void TestMethod1()
{
    Action<SomeClass, int> intInvoke = (o, data) => o.SomeMethod(data);
    Action<SomeClass, string> stringInvoke = (o, data) => o.SomeMethod(data);

    var list = new List<MyData> 
    {
        new MyData<int> { Data = 10, OnTypedInvoke = intInvoke },
        new MyData<string> { Data = "abc", OnTypedInvoke = stringInvoke }
    };

    var someClass = new SomeClass();
    foreach (var item in list)
    {
        item.OnInvoke(someClass);
    }
}

public abstract class MyData
{
    public Action<SomeClass> OnInvoke;
}

public class MyData<T> : MyData
{
    public T Data { get; set; }
    public Action<SomeClass, T> OnTypedInvoke 
    { set { OnInvoke = (o) => { value(o, Data); }; } }
}

public class SomeClass
{
    public void SomeMethod(string data)
    {
        Console.WriteLine("string: {0}", data);
    }

    public void SomeMethod(int data)
    {
        Console.WriteLine("int: {0}", data);
    }
}
public void TestMethod1()
{
动作intInvoke=(o,数据)=>o.SomeMethod(数据);
Action stringInvoke=(o,data)=>o.SomeMethod(data);
变量列表=新列表
{
新MyData{Data=10,OnTypedInvoke=intInvoke},
新建MyData{Data=“abc”,OnTypedInvoke=stringInvoke}
};
var someClass=new someClass();
foreach(列表中的变量项)
{
项目.OnInvoke(someClass);
}
}
公共抽象类MyData
{
禁止吸烟的公众行动;
}
公共类MyData:MyData
{
公共T数据{get;set;}
关于Typedinvoke的公共行动
{set{OnInvoke=(o)=>{value(o,数据);};}}
}
公共类
{
公共方法(字符串数据)
{
WriteLine(“字符串:{0}”,数据);
}
公共方法(int数据)
{
WriteLine(“int:{0}”,数据);
}
}

MyData如何允许调用SomeMethod(int)?能否详细说明SomeMethod的功能?我们可能会更好地帮助您。SomeMethod的功能与此无关。我要补充的是,SomeMethod(object)没有定义。您的基本设计有缺陷。我建议您提出一个问题,详细说明需求和解决方案,并征求建议。好的,现在我会像这样使用它:List List=new List();List.Add(new MyData());List.Add(new MyData());SomeMethod(List[0].Data);不知何故,我需要让SomeMethod()接受一个对象。我
SomeMethod(myData.Data.Data);
public void SomeMethod<T>(T value)
{
    Type type = typeof(T);

    if (type == typeof(int))
    {
        SomeMethod((int) (object) value); // sadly we must box it...
    }
    else if (type == typeof(float))
    {
        SomeMethod((float) (object) value);
    }
    else if (type == typeof(string))
    {
        SomeMethod((string) (object) value);
    }
    else
    {
        throw new NotSupportedException(
            "SomeMethod is not supported for objects of type " + type);
    }
}
public void TestMethod1()
{
    Action<SomeClass, int> intInvoke = (o, data) => o.SomeMethod(data);
    Action<SomeClass, string> stringInvoke = (o, data) => o.SomeMethod(data);

    var list = new List<MyData> 
    {
        new MyData<int> { Data = 10, OnTypedInvoke = intInvoke },
        new MyData<string> { Data = "abc", OnTypedInvoke = stringInvoke }
    };

    var someClass = new SomeClass();
    foreach (var item in list)
    {
        item.OnInvoke(someClass);
    }
}

public abstract class MyData
{
    public Action<SomeClass> OnInvoke;
}

public class MyData<T> : MyData
{
    public T Data { get; set; }
    public Action<SomeClass, T> OnTypedInvoke 
    { set { OnInvoke = (o) => { value(o, Data); }; } }
}

public class SomeClass
{
    public void SomeMethod(string data)
    {
        Console.WriteLine("string: {0}", data);
    }

    public void SomeMethod(int data)
    {
        Console.WriteLine("int: {0}", data);
    }
}