tags:

views:

824

answers:

5

EDITED to show real example

How can I call a generic function from a generic type passed to a function? This seems like it should be intuitive, but I can't seem to get it to work.

For example, can I call the cache.ResetCache() function in LocalDataObjectEngine below?

The error I'm getting is 'Type T cannot be used as a parameter'

public interface ISimpleCache<T1>
{    
    ...
    void ResetCache<T>() where T : T1;
}

internal class LocalDataObjectEngine_Cache : ISimpleCache<IBrokeredDataObject>
{
    ISimpleCache<IBrokeredDataObject> _cache;

    ...

    public void ResetCache<T>() where T : IBrokeredDataObject
    {
        //logic here
    }

    ...
}

public partial class LocalDataObjectEngine : IEngine
{
    ISimpleCache<IBrokeredDataObject> _cache  = new LocalDataObjectEngine_Cache();

    public void ResetCache<T>() where T : IBrokeredDataObject
    {
        _cache.ResetCache<T>();
    }
}

}
+1  A: 

I'm not sure what's going on unless there's something in your definition of IBrokeredDataObject. What you've written looks right and compiles fine for me.

[Edited to match the edit in the OP]

lc
+1  A: 

First of all, why do you need to specify a generic type in your methods? The class already specifies the generic type, you'll have access to it in your methods:

public interface ISimpleCache<T1>
{    
    ...
    void ResetCache();
}

which makes the class that implements the interface much simpler:

internal class LocalDataObjectEngine_Cache : ISimpleCache<IBrokeredDataObject>
{
    ISimpleCache<IBrokeredDataObject> _cache;

    ...

    public void ResetCache();
    {
        //logic here with access to IBrokeredDataObject if needed
    }

    ...
}

the same goes for the last method, just call

_cache.ResetCache();

however, if you really need to specify the generic type in the methods for some reason, do as below


Let's start:

Why don't you use T1 in the method instead of specifying T should be like T1?

public interface ISimpleCache<T1>
{    
    ...
    void ResetCache<T1>();
}

In your LocalDataObjectEngine_Cache, you don't have to specify T again, just use IBrokeredDataObject (if you don't implement the method, and right-click on the interface name to choose "Implement interface", it will write it as below:

internal class LocalDataObjectEngine_Cache : ISimpleCache<IBrokeredDataObject>
{
    ISimpleCache<IBrokeredDataObject> _cache;

    ...

    public void ResetCache<IBrokeredDataObject>();
    {
        //logic here
    }

    ...
}

Then from your last class, just call it again by specifying the actual class you want T to be:

public partial class LocalDataObjectEngine : IEngine
{
    ISimpleCache<IBrokeredDataObject> _cache  = new LocalDataObjectEngine_Cache();

    public void ResetCache<IBrokeredDataObject>()
    {
        _cache.ResetCache<IBrokeredDataObject>();
    }
}
GoodEnough
I wanted to differentiate between T1 as a cache base object and T as a typed object derived from T, as there are 0 - n different types of objects that may live in the cache, all derivatives of IBrokeredDataObject, but I want to specify a single type to flush.
johnc
Therefore resetting the cache of ResetCache<IBrokeredDataObject> would not meet my requirements as I can't tell the engine to Remove all 'DerivedDataObjectType1' as opposed to 'DerivedDataObjectType2' from the cache
johnc
As long as your class implements the IBrokeredDataObject, you can use it when declaring the _cache object. ISimpleCache<SomeClassThatImplementsTheInterface> _cache = new ...will work.
GoodEnough
+1  A: 

After removing the ..., the reference to IEngine, and providing an empty IBrokeredDataObject interface, your code compiles without any problems.

Please provide a short but complete example which doesn't compile. Ideally, create a new project with a single file in, put all your code in there, and make it as simple as possible while showing the same error. Then just cut and paste into here. That way we don't need to fix up "..." etc or remove references to interfaces which we don't have declarations for.

Jon Skeet
Thanks, I've posted the answer, it was your reference to IEngine that helped me track down the culprit
johnc
A: 

Found it, Jon Skeet's reference to removing IEngine pointed me in the right direction, there was a

void ResetCache<T>() where T : IDataObject

on IEngine (IDataObject is a base if IBrokeredDataObject), that I changed to

void ResetCache<T>() where T : IBrokeredDataObject

Thanks all for tolerating my bug, +1 to you all

johnc
A: 

0 vote down

Hi i have a question!

abstract public class AbstractExpireRule{

// with methos

protected abstract T getvalue();

}

How can we extend this class to return let me say integer or what ever?

public class ExpireDaysFromFirstLogin extends AbstractExpireRule {

@Override public Integer getvalue() { return new Integer(5); }

}

this dosent work

if we take out the generics:

@Override public Integer getvalue() { return new Integer(durationInDays); }

it works but TYPE SAFETY...

Type safety: The return type Integer for getvalue() from the type ExpireDaysFromFirstLogin needs unchecked conversion to conform to T from the type AbstractExpireRule

same like i discard the generics from the abstract class?!

Can some one help...

baze
Click the "Ask Question" button in the upper right hand corner. The answers section is not the place for new questions.
Jace Rhea
you should start a new question thread
Luiscencio