简体   繁体   English

如何实现泛型方法?

[英]How to implement generic method?

I have such class (some kind of factory)我有这样的课(某种工厂)

   class CacheFactory
    {
        private ConfigCache m_ConfigCache = null;

        public CacheFactory(ConfigCache configCache)
        {
            m_ConfigCache = configCache;
        }

        public CACHE_TYPE GetCache<CACHE_TYPE>()
            where CACHE_TYPE : BaseCache
        {
            BaseCache result = new NOT_DEFINED_CACHE();

            .....

            return result;    <---- This line
        }
    }

And in this class I have GetCache() method, that has return type of <CACHE_TYPE> where CACHE_TYPE: BaseCache在这个类中,我有GetCache()方法,它的返回类型为<CACHE_TYPE> where CACHE_TYPE: BaseCache

Then in body of this method I create BaseCache instance and try to return him , but here I have an warning in line that I marked above然后在这个方法的主体中,我创建了BaseCache实例并尝试返回他,但在这里我有一个警告,我在上面标记了

Cannot implicitly convert BaseCache to CACHE_TYPE...无法将 BaseCache 隐式转换为 CACHE_TYPE...

How is it possible if CACHE_TYPE inherent from BaseCache ??如果CACHE_TYPE固有的BaseCache怎么可能?

And hot to solve this issue in right way?以正确的方式解决这个问题?

EDIT编辑

Ok, if I need to return derived type I have one more class ConfigCache that inherit from BaseCache , but anyway I get the same error, that ConfigCache cannot be converter to CACHE_TYPE ... Inspite this class is derived ...好的,如果我需要返回派生类型,我还有一个继承自BaseCacheConfigCache ,但无论如何我得到相同的错误,即ConfigCache cannot be converter to CACHE_TYPE ......尽管这个类是派生的......

EDIT2编辑2

Thanks for everyone.谢谢大家。 There is what I have now, what do you think about it?我现在拥有的东西,你怎么看?

        private CACHE_TYPE GetCache<CACHE_TYPE>()
            where CACHE_TYPE : BaseCache, new()
        {
            var result = new CACHE_TYPE();

            if (typeof(CACHE_TYPE) == typeof(ConfigCache))
            {
                if (m_ConfigCache == null)
                {
                    m_ConfigCache = new ConfigCache();
                }

                result = m_ConfigCache as CACHE_TYPE;
            }

            return result;
        }

You cannot.你不能。 The error message is right.错误信息是正确的。

You promised to return a derived type and yet you return a base type, knowing that it will be right, because that is what you instantiated.你承诺返回一个派生类型,但你返回一个基类型,知道它是正确的,因为那是你实例化的。 That is not how a compiler works.这不是编译器的工作方式。 result needs to be of type CACHE_TYPE . result需要是CACHE_TYPE类型。

I don't understand why this is necessary at all.我不明白为什么这是必要的。 Can you describe why this factory is needed and how it will be used?你能描述一下为什么需要这个工厂以及它将如何使用吗? The approach itself is not very true for the factory.这种方法本身对于工厂来说并不是很正确。 But for what you described, the following may come up:但是对于您描述的情况,可能会出现以下情况:

class CacheFactory<TConfigCache> 
    where TConfigCache: class, BaseCache, new()
{
    public CacheFactory(TConfigCache configCache)
    {
        ConfigCache = configCache;
    }

    private TConfigCache ConfigCache { get; set; }

    public TCache GetCache<TCache>()
        where TCache: class, BaseCache, new()
    {
        if (typeof(TConfigCache) == typeof(TCache))
        {
            if (ConfigCache == null)
            {
                ConfigCache = new TConfigCache();
            }
            return ConfigCache as TCache;
        }

        return new TCache();
    }
}

Be sure to add class in the generic requirements.确保在通用需求中添加

EDIT编辑

Or you can use not generic implementation.或者您可以使用非通用实现。

class CacheFactory{
    public CacheFactory(ConfigCache configCache)
    {
        ConfigCache = configCache;
    }

    private ConfigCache ConfigCache { get; set; }

    public TCache GetCache<TCache>()
        where TCache: class, BaseCache, new()
    {
        if (typeof(ConfigCache) == typeof(TCache))
        {
            if (ConfigCache == null)
            {
                ConfigCache = new ConfigCache();
            }
            return ConfigCache as TCache;
        }

        return new TCache();
    }
}

EDIT 2编辑 2

Its full code of my test application and its work.它是我的测试应用程序及其工作的完整代码。 Maybe it will help.也许它会有所帮助。

interface BaseCache { }

class ConfigCache : BaseCache { }

class MyCache : BaseCache { }

class CacheFactory{
    public CacheFactory(ConfigCache configCache)
    {
        ConfigCache = configCache;
    }

    private ConfigCache ConfigCache { get; set; }

    public TCache GetCache<TCache>()
        where TCache: class, BaseCache, new()
    {
        if (typeof(ConfigCache) == typeof(TCache))
        {
            if (ConfigCache == null)
            {
                ConfigCache = new ConfigCache();
            }
            return ConfigCache as TCache;
        }

        return new TCache();
    }
}


class Program
{
    static void Main(string[] args)
    {
        var configCache = new ConfigCache();
        var factory = new CacheFactory(configCache);
        var cache1 = factory.GetCache<ConfigCache>();
        var cache2 = factory.GetCache<MyCache>();

        Print(configCache);
        Print(cache1);
        Print(cache2);
        Console.ReadKey();
    }

    static void Print(BaseCache cache)
    {
        Console.WriteLine("BaseCache: {0}, {1}", cache.GetType().FullName, cache.GetHashCode());
    }
}

Your return type is the derived class, but you've attempted to return a base class.您的返回类型是派生类,但您已尝试返回基类。 This isn't allowed .这是不允许的 If your derived class has a parameterless constructor you can add a new() constraint and do the following.如果您的派生类具有无参数构造函数,您可以添加一个new()约束并执行以下操作。

private T GetCache<T>()
    where T : BaseCache, new()
{
    var result = new T();

    return result;
}

Your edit suggests you are trying to return a member variable.您的编辑表明您正在尝试返回成员变量。 I would suggest making different methods to return different variables.我建议使用不同的方法来返回不同的变量。

private ConfigCache GetConfigCache()
{
    if (m_ConfigCache == null)
        m_ConfigCache = new ConfigCache();

    return m_ConfigCache;
}

Or even just a property.或者甚至只是一个财产。

private ConfigCache _config;

private ConfigCache Config
{
    get
    {
        if (_config == null)
            _config = new ConfigCache();

        return _config;
    }
}

Finally, I would advise against it, but if you do want to continue down your path, something like the following would work.最后,我建议不要这样做,但是如果您确实想继续前进,则可以使用以下方法。

private T GetCache<T>()
    where T : BaseCache
{
    if (typeof(T) == typeof(ConfigCache))
    {
         if (m_ConfigCache == null)
             m_ConfigCache = new ConfigCache();

        return (T)(object)m_ConfigCache;
    }

    // Support for other types of caches.
}

Imagine you could do this, see what happens here:想象一下你可以这样做,看看这里会发生什么:

class BaseCache {}
class NOT_DEFINED_CACHE : BaseCache {}
class OTHER_CACHE : BaseCache {}

var factory = new CacheFactory();
OTHER_CACHE cache = factory.GetCache<OTHER_CACHE>(); // Oh dear, I wanted OTHER_CACHE but got NOT_DEFINED_CACHE!

The fact is that you're trying to create a generic method that's doing something very specific ie creating a NOT_DEFINED_CACHE instance.事实是您正在尝试创建一个通用方法,该方法正在做一些非常具体的事情,即创建一个NOT_DEFINED_CACHE实例。

What you could do is create an instance of NOT_DEFINED_CACHE with the properties defined in BaseClass set:您可以做的是创建一个NOT_DEFINED_CACHE的实例, NOT_DEFINED_CACHE使用BaseClass集中定义的属性:

class BaseCache
{
    int X { get; set; }
    int Y { get; set; }
    int Z { get; set; }
}
class NOT_DEFINED_CACHE : BaseCache {}

public CACHE_TYPE GetCache<CACHE_TYPE>() where CACHE_TYPE : BaseCache, new()
{
    CACHE_TYPE result = new CACHE_TYPE();
    result.X = 1:
    result.Y = 2:
    result.Z = 3:
    return result;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM