C# - 添加实现接口到字典的对象

use*_*923 14 c# generics dictionary

我有一本字典:

private Dictionary<Type, IExample> examples;
Run Code Online (Sandbox Code Playgroud)

我有两个实现接口的类:

public class Example1 : IExample
{
}

public class Example2 : IExample
{
}
Run Code Online (Sandbox Code Playgroud)

我已经创建了一种从字典中获取实例的方法,如果它存在但是我试图找出一种方法来实例化一个新对象(如果它不存在).

public T GetExample<T>() where T : IExample
{
    // Return the signal if it exists
    if (examples.ContainsKey(typeof(T)))
    {
        IExample value;

        if (!examples.TryGetValue(typeof(T), out value))
        {
            // unable to get value
        }

        return (T)value;
    }

    // Stuck on this line here. How exactly do I instantiate a new example if it doesn't exist.
    examples.Add(typeof(T), new );

    return default(T);
}
Run Code Online (Sandbox Code Playgroud)

这样的事情可能吗?

Ehs*_*jad 13

您需要在无参数构造函数的泛型方法上添加泛型类型参数约束,然后您可以实例化类型T参数,如new T():

public T GetExample<T>() where T : IExample,class,new()
{
       IExample value;

       if (examples.TryGetValue(typeof(T), out value))
       {
           return (T)value;
       }


   T obj =  new T(); // create instance of T and use further down in code it's reference
   examples.Add(typeof(T),obj );

   return obj ;
}
Run Code Online (Sandbox Code Playgroud)

并且return default(T);不会返回类null的新实例T(引用类型)默认值是null,我怀疑你想在return new T();那里做什么,它会创建一个新对象并将它的引用返回给调用者.

  • @EhsanSajjad我将`ContainsKey`删除为`TryGetValue`本身就足以不引发异常. (2认同)

das*_*ght 8

尽管您当然可以创建一个需要默认构造函数的类型约束,但它通常过于拘束:代码的用户可能不愿意将默认构造函数设置为public,或者根本没有默认构造函数.

更灵活的方法需要一个创建缺少对象的委托:

public T GetExample<T>(Func<T> make) where T : IExample, class {
    IExample value;
    if (examples.TryGetValue(typeof(T), out value)) {
        return (T)value;
    }
    T res =  make();
    examples.Add(typeof(T), res);
    return res;
}
Run Code Online (Sandbox Code Playgroud)

这样,当您需要的对象未缓存在中时,调用者可以控制如何创建新对象examples.您的代码回调"按需",因此对象创建逻辑仍然牢牢地隐藏在调用者的代码中

var e = exampleFactory.GetExample<MyExample>(
    () => new MyExample(firstParameter, secondParameter)
);
Run Code Online (Sandbox Code Playgroud)