Ale*_*ean 8 c# generics constructor initialization
我有这个通用的单例看起来像这样:
public class Cache<T>
{
private Dictionary<Guid, T> cachedBlocks;
// Constructors and stuff, to mention this is a singleton
public T GetCache(Guid id)
{
if (!cachedBlocks.ContainsKey(id))
cachedBlocks.Add(id, LoadFromSharePoint(id))
return cachedBlocks[id];
}
public T LoadFromSharePoint(Guid id)
{
return new T(id) // Here is the problem.
}
}
Run Code Online (Sandbox Code Playgroud)
错误消息是:
无法创建类型为T的实例,因为它没有new()约束.
我必须提到我必须传递该id参数,并且没有其他方法可以这样做.任何关于如何解决这个问题的想法都将受到高度赞赏.
Dan*_*ker 14
通常,您会将类型约束为T具有默认构造函数的类型并调用它.然后,您必须添加方法或属性才能提供id实例的值.
public static T LoadFromSharePoint<T>(Guid id)
where T : new() // <-- Constrain to types with a default constructor
{
T value = new T();
value.ID = id;
return value;
}
Run Code Online (Sandbox Code Playgroud)
或者,因为您指定必须id通过构造函数提供参数,所以可以使用反射调用参数化构造函数.您必须确保该类型定义了您要调用的构造函数.您不能将泛型类型约束为T具有除默认构造函数之外的特定构造函数的类型.(例如where T : new(Guid)不起作用.)
例如,我知道有一个构造new List<string>(int capacity)上List<T>,它可以调用这样的:
var type = typeof(List<String>);
object list = Activator.CreateInstance(type, /* capacity */ 20);
Run Code Online (Sandbox Code Playgroud)
当然,您可能希望之后进行一些转换(to T).
为此,您应该指定是什么T。你Cache<T>能装什么吗?Tiger,Fridge并且int呢?那不是声音设计。你应该约束它。您需要一个实例,T该实例将使用 aGuid来构造实例。那不是通用的T. 它是一个非常具体的T. 将您的代码更改为:
public class Cache<T> where T : Cacheable, new()
{
private Dictionary<Guid, T> cachedBlocks;
// Constructors and stuff, to mention this is a singleton
public T GetCache(Guid id)
{
if (!cachedBlocks.ContainsKey(id))
cachedBlocks.Add(id, LoadFromSharePoint(id))
return cachedBlocks[id];
//you're first checking for presence, and then adding to it
//which does the same checking again, and then returns the
//value of key again which will have to see for it again.
//Instead if its ok you can directly return
//return cachedBlocks[id] = LoadFromSharePoint(id);
//if your LoadFromSharePoint is not that expensive.
//mind you this is little different from your original
//approach as to what it does.
}
public T LoadFromSharePoint(Guid id)
{
return new T { Key = id }; // Here is no more problem.
}
}
public interface Cacheable
{
Guid Key { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
现在从接口派生所有可缓存的(无论T您将传递给它的是什么Cache<T>)Cacheable。
| 归档时间: |
|
| 查看次数: |
9939 次 |
| 最近记录: |