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

Sté*_*écy 27 .net c# generics list

具有以下通用类,其中包含以下string, int, float, long类型:

public class MyData<T>
{
    private T _data;

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

    public T Data { get { return _data; } }
}
Run Code Online (Sandbox Code Playgroud)

我想弄清楚MyData<T>每个项目的不同之处T.

我希望能够从列表中访问项目并获取其值,如下面的代码所示:

MyData<> myData = _myList[0];    // Could be <string>, <int>, ...
SomeMethod (myData.Data);
Run Code Online (Sandbox Code Playgroud)

其中,SomeMethod()声明如下:

public void SomeMethod (string value);
public void SomeMethod (int value);
public void SomeMethod (float value);
Run Code Online (Sandbox Code Playgroud)

更新:

SomeMethod()来自另一个我无法控制SomeMethod(object)但不存在的等级.


但是,我似乎无法找到让编译器开心的方法.

有什么建议?

谢谢.

Jos*_*eph 13

我认为您遇到的问题是因为您尝试创建泛型类型,然后创建该泛型类型的列表.您可以通过外包您尝试支持的数据类型(例如IData元素)来完成您尝试执行的操作,然后使用IData约束创建MyData泛型.这样做的缺点是你必须创建自己的数据类型来表示你正在使用的所有原始数据类型(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; }
}
Run Code Online (Sandbox Code Playgroud)

然后你的实现将是这样的:

var myData = new MyData<MyString, string>(new MyString("new string"));    
// Could be MyString, MyInt, ...
myData.Data.SomeMethod();
Run Code Online (Sandbox Code Playgroud)

这是一个更多的工作,但你得到了你想要的功能.

更新: 从您的界面中删除SomeMethod,然后执行此操作

SomeMethod(myData.Data.Data);
Run Code Online (Sandbox Code Playgroud)


Leo*_*alt 8

代表们可以真正帮助简化这一点,并保持类型安全:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)


Amy*_*y B 6

只需使用ArrayList并忘记MyData<T>类型.

ArrayList myStuff = getStuff();
float x = myStuff.OfType<float>().First();
SomeMethod(x);
string s = myStuff.OfType<string>().First();
SomeMethod(s);
Run Code Online (Sandbox Code Playgroud)

问题MyData<T>在于您期望编译器检查仅在运行时已知的类型.编译器检查编译时已知的类型.