C#-用于修改特定于每种类型的数据结构的通用函数

C#-用于修改特定于每种类型的数据结构的通用函数,c#,generics,C#,Generics,我在泛型方面遇到了一些问题 我想写一个泛型函数,给定一个类型,修改该类型的数据结构 public static Dictionary<int, User> Users = new Dictionary<int, User>(); public static Dictionary<int, Item> Items = new Dictionary<int, Item>(); public static Dictionary<int, Store

我在泛型方面遇到了一些问题

我想写一个泛型函数,给定一个类型,修改该类型的数据结构

public static Dictionary<int, User> Users = new Dictionary<int, User>();
public static Dictionary<int, Item> Items = new Dictionary<int, Item>();
public static Dictionary<int, Store> Stores = new Dictionary<int, Store>();

public static void AddStuff<T>(T stuffToAdd)
{
    (What dict goes here?).TryAdd(stuffToAdd.Id, stuffToAdd)
}
public static Dictionary Users=new Dictionary();
公共静态字典项=新字典();
公共静态字典存储=新字典();
公共静态void AddStuff(T stuff toadd)
{
(这里有什么命令?).TryAdd(stuffToAdd.Id,stuffToAdd)
}
我想这样称呼它:

AddStuff<User>(some_user);
AddStuff(一些用户);
因此,根据调用它的类型,我必须找出如何找到与该类型关联的数据结构,并从中添加/删除内容。对我有什么想法吗


编辑:我有20本这样的字典

您可以使用if/else if或开关(仅限C#7 up)来完成此操作

public static void AddStuff<T>(T stuffToAdd)
{
    switch (stuffToAdd)
    case User:
        Users.TryAdd(stuffToAdd.Id, stuffToAdd);
    // More cases
}
公共静态void AddStuff(T stuff toadd)
{
开关(填充到添加)
案例用户:
Users.TryAdd(stuffToAdd.Id,stuffToAdd);
//更多案例
}

附言:在手机和公交车上。所以,请做必要的修改,使其编译等也正如其他人所指出的,你实际上不需要在这里泛型。所以不要用我在这里展示的东西

为了能够访问Id属性,您需要一个公共接口和一个类型约束。在我的示例中,我包含了一个
IHasId
接口,因此所有域类型都有可用的ID

要选择字典,你只需要把它们放在一本更大的字典里。在我的示例中,我将其称为字典

//This interface allows you to specify a type constraint so AddStuff can use the Id property
public interface IHasId
{
    int Id { get; }
}

public class User  : IHasId { public int Id { get; set; } }
public class Item  : IHasId { public int Id { get; set; } }
public class Store : IHasId { public int Id { get; set; } }

public class Program
{
    public static Dictionary<int, User> Users = new Dictionary<int, User>();
    public static Dictionary<int, Item> Items = new Dictionary<int, Item>();
    public static Dictionary<int, Store> Stores = new Dictionary<int, Store>();

    //This "outer" dictionary will allow AddStuff to look up the right dictionary based on the type.
    public static Dictionary<Type,IDictionary> dictionaries = new Dictionary<Type,IDictionary>
    {
        { typeof(User ), Users },
        { typeof(Item ), Items }, 
        { typeof(Store), Stores}
    };

    public static void AddStuff<TValue>(TValue stuffToAdd) where TValue  : IHasId
    {
        IDictionary d = dictionaries[typeof(TValue)] as Dictionary<int, TValue>;
        d.Add(stuffToAdd.Id, stuffToAdd);
    }

    public static void Main()
    {
        AddStuff( new User  { Id = 1} );
        AddStuff( new User  { Id = 2} );
        AddStuff( new Item  { Id = 3} );
        AddStuff( new Item  { Id = 4} );
        AddStuff( new Store { Id = 5} );
        AddStuff( new Store { Id = 6} );

        Console.WriteLine("Users:  " + string.Join(",", Users.Select( u => u.Value.Id )));
        Console.WriteLine("Items:  " + string.Join(",", Items.Select( i => i.Value.Id )));
        Console.WriteLine("Stores: " + string.Join(",", Stores.Select( s => s.Value.Id )));
    }
}

看到你的用法
AddStuff(一些用户)
,也可能是
AddStuff(一些用户)
,我不认为有一个通用的。而不是使用无法编译时验证的东西(是通用的
用户
存储
或其他东西)。例如,
AddStuff(“oops无效用法”)
会导致运行时问题。您还可以对每种类型使用重载。您可以有一个私人助手函数,如Paul的扩展示例

使用类似John Wu使用
IHasId
界面的想法,您可以创建如下私人助手:

private static void AddStuff<T>(Dictionary<int, T> dict, T stuffToAdd)
    where TValue  : IHasId
{
    dict.TryAdd(stuffToAdd.Id, stuffToAdd)
}
我在泛型方面遇到了一些问题

是的,你是。注意那种感觉。它告诉你你滥用仿制药

我想写一个泛型函数,给定一个类型,修改该类型的数据结构

public static Dictionary<int, User> Users = new Dictionary<int, User>();
public static Dictionary<int, Item> Items = new Dictionary<int, Item>();
public static Dictionary<int, Store> Stores = new Dictionary<int, Store>();

public static void AddStuff<T>(T stuffToAdd)
{
    (What dict goes here?).TryAdd(stuffToAdd.Id, stuffToAdd)
}
我最好的建议是:不要再想要那个了。泛型应该是泛型的。这就是为什么它们被称为泛型。如果您正在基于泛型类型参数执行不同的操作,那么您的代码不是泛型的

我想这样称呼它:
AddStuff(一些用户)

别再想要了

相反,编写三个方法,并像这样调用它们:

AddUserStuff(someUser);
AddItemStuff(someItem);
AddStoreStuff(someStore);
等等。从逻辑上讲,有三种方法可以做三件不同的事情,因此它们不是通用的。写三种方法

编辑:我有20本这样的字典


写20个方法。这并不难,而且比编写一个包含20个案例的“泛型”方法更容易,因为它看起来是泛型的,但实际上不是。你真的需要泛型吗?如果只是重载,它的性能会好得多。我不认为在用法上有什么不同。我同意@NevilleNazerane。这确实提出了一个问题,当你有一个明确的有限和最少数量的字典时,为什么要使用泛型。这只是一个例子。我有20本这样的字典。我是否仍要为它们中的每一个创建一个特定的add函数?是的,请查看下面的所有解决方案。每件事都需要你为每本字典做一些额外的工作。逃避它的唯一方法是使用反射和动态。这些通常是最后的度假胜地。反射很重,动态性很高,这是不可能的。请参见这里的@inclusion-在C#6中是可能的,尽管泛型的使用是多余的,因为如果
Stuff添加
的类型为
对象
,则泛型可以工作@daniel@DanielB-参见@Sааааааӽ:在C#7.0中添加了开关中的类型模式匹配。Paul删除了他的答案。他为
字典发布了一个扩展函数
我的问题最初只是一个例子,但实际上我的产品中有20个不同类型的字典。我应该有20个这样的方法来做同样的事情吗?@noblerare:你的选择是:写20个方法,或者写一个有20个案例的方法,然后当你添加第21个字典时,它就是一个bug农场,而忘记将案例添加到你的“泛型”方法中,而这个方法实际上不是泛型的。前者既简单又安全:但这将是一个很好的机会,让我们也可以重新审视架构决策,该决策导致20个不同的字典都键入了一个int。假设您使用一个唯一的标识符(Guid)来标识实体。现在,您可以构建一个将
Guid
映射到
object
的字典。有了这些泛型,为什么不使用内置的东西来处理数据存储呢?它们已经具备了您正在寻找的所有功能for@noblerare:更一般地说,问问自己这里是否有实现自动化的机会。您有一些工厂正在分发用户并将ID与他们关联。也许工厂对象应该自动提供id到对象查找的服务。为什么要调用一个方法来将项添加到字典中?将其作为工厂的实施细节。
AddUserStuff(someUser);
AddItemStuff(someItem);
AddStoreStuff(someStore);