Pass Interface to a generic attribute of a class in C#? - c#

When a do this:
public class ball {
ITeste<IItem> Teste{ get; set; }
}
I got the error:
'IItem' must be a non-abstract type with a public parameterless
constructor in order to use it as parameter 'T' in the generic type or
method
ITeste:
public interface ITeste<T>
where T : IItem, IEquatable<T>, new()
{
//ITeste code
}
IItem:
public interface IItem : IEquatable<IItem>
{
//IItem Code
}
It seems to be a simple question, but I could not find the answer. Any help it would be appreciated.

Remove new() from the constraints for ITeste
ITeste:
public interface ITeste<T>where T : IItem, IEquatable<T>
{
//ITeste code
}

Related

Ninject: can't register generic interface to many other interfaces

I'm trying to register a generic interface in Ninject, and then I want to some other interface to that generic interface:
public interface ISE<T> { }
public class SE<T> : ISE<T> { }
public interface IConcreteSE_A : ISE<SomeClass_A> { }
public interface IConcreteSE_B : ISE<SomeClass_B> { }
public interface IConcreteSE_C : ISE<SomeClass_C> { }
kernel.Bind(typeof(ISE<>)).To(typeof(SE<>));
kernel.Bind<IConcreteSE_A>().To(typeof(SE<>));
kernel.Bind<IConcreteSE_B>().To(typeof(SE<>));
kernel.Bind<IConcreteSE_C>().To(typeof(SE<>));
But I get an error: The number of generic arguments given is not equal to the number of general type definition arguments when I try to inject e.g. IConcreteSE_A to my web api controller.
how to fix it ?
This is because there is no implicit reference conversion between IConcreteSE_A and ISE<SomeClass_A>. In other words there is no guarantee that SE<SomeClass_A>, which implements ISE<SomeClass_A>, actually satisfies the implementation for IConcreteSE_A.
You can fix this by creating a concrete class that implements both interfaces and then bind to that.
public class SE<T> : ISE<T> { }
public class SomeClassA { }
public class ConcreteSE_A : ISE<SomeClass_A>, IConcreteSE_A { }
public interface IConcreteSE_A : ISE<SomeClass_A> { }
kernel.Bind(typeof(ISE<>)).To(typeof(SE<>));
kernel.Bind<IConcreteSE_A>().To<ConcreteSE_A>();

Implementing a Generic Interface and a Non Generic Interface

I have two contracts (one Generic Interface and the other Non-Generic) as follows:
public interface IGenericContract<T> where T : class
{
IQueryable<T> GetAll();
}
public interface INonGenericContract
{
string GetFullName(Guid guid);
}
I have a class implementing both
public class MyClass<T> :
IGenericContract<T> where T : class, INonGenericContract
{
public IQueryable<T> GetAll()
{
...
}
public string GetFullName(Guid guid)
{
...
}
}
Everything is fine until this point when I compile it.
But now when I try using this class I run into this error
"error CS0311: The type 'string' cannot be used as type parameter 'T' in the generic type or method 'ConsoleApplication1.MyClass'. There is no implicit reference conversion from 'string' to 'ConsoleApplication1.INonGenericContract'."
class Program
{
static void Main(string[] args)
{
MyClass<string> myClass = new MyClass<string>(); //Error
}
}
If I do not implement the Non-generic contract it works fine. What could be wrong here ?
Thanks
In your code INonGenericContract is part of generic constraint, as it placed after where.
public class MyClass<T> :
IGenericContract<T> where T : class, INonGenericContract
You likely want that:
public class MyClass<T> :
IGenericContract<T>, INonGenericContract where T : class
you are very close, what you have to do is implement the non generic interface, not put a constrain.
public class MyClass<T> :
IGenericContract<T>, INonGenericContract where T : class
{
public IQueryable<T> GetAll()
{
return null;
}
public string GetFullName(Guid guid)
{
return null;
}
}
now you can do this
MyClass<string> myClass = new MyClass<string>();
According what you show
public class MyClass<T> : IGenericContract<T> where T : class, INonGenericContract
T must implement INonGenericContract and string doesn't implement it. In short, string is not a valid parameter for class MyClass
If what you're looking for is implementing IGenericContract<T> AND INonGenericContract you should have
public class MyClass<T> : INonGenericContract, IGenericContract<T>
there is no need to have where T : class since IGenericContract<T> already has that constraint.

Assigning implementation of a generic interface to a property

I have an interface
public interface IStrategy<T> where T : BaseModel
{
T GetModel(Guid userId);
}
and a concrete class inheriting the interface specifying that it should be a ConcreteModel
public class ConcreteStrategy: IStrategy<ConcreteModel>
{
ConcreteModel GetModel(Guid userId) { ... }
}
Now in the following method I can pass a new instance of ConcreteStrategy and everything works
public class Manager
{
public TModel GetContentModel<TModel>(IStrategy<TModel> strategy, Guid userId)
where TModel : ModelBase
{
return strategy.GetContentModel(userId);
}
}
But if I try to assign it to a property like this I get an error
public class Strategies
{
public static IStrategy<ModelBase> MyStrategy { get; set; }
}
Strategies.MyStrategy = new ConcreteStrategy();
Is there a way I can achieve this in C# ?
I want to be able to make a factory method that encapsulates the logic for which strategy to use and just return an instance of some type of strategy class (like ConcreteStrategy).
The error I am getting is:
Cannot implicitly convert type IStrategy<ModelBase> to IStrategy<ConcreteModel>
You need to make your interface covariant:
public interface IStrategy<out T> where T : BaseModel
Note that it will work only if T only appears in an output position in the interface (which is the case in the code you have shown, but I don't know if it's your real code).

Generics inheritance compile error

I'm getting a compile error when I try to compile this
The type 'WpfApplication2.CommandInstrumentTrade' cannot be used as type parameter 'T' in the generic type or method 'WpfApplication2.GenericWindowBase'. There is no implicit reference conversion from 'WpfApplication2.CommandInstrumentTrade' to 'WpfApplication2.GenericCommandBase'
public interface IBaseClass
{
int ID { get; set; }
}
public class BaseClass : IBaseClass
{
public int ID { get; set; }
}
public class DerivedClass : BaseClass
{
}
public class Command
{
}
public class GenericCommandBase<T> : Command where T : IBaseClass
{
}
public class DerivedGenericCommand : GenericCommandBase<DerivedClass>
{
}
public class GenericWindowBase<T> where T : GenericCommandBase<IBaseClass>
{
}
public class DerivedGenericWindow : GenericWindowBase<DerivedGenericCommand> // this line fails
{
}
The issue is that Generic<Derived> does not satisfy the condition where T : Generic<Base>. Even if Derived derives from Base, Generic<Derived> does not derive from Generic<Base>
There are many questions like that in StackOverflow.
Try reading those:
C# Generics Inheritance
generic inheritance in C#?
Inheritance doesn't compose with generics. You need to create some kind of converter from one to another. Maybe if you present some less abstract code we could help You

Generic inheritance in C#: Cannot implicitly convert type 'MyWidget' to 'IWidget'

I'm having a problem setting up inheritance with generics.
In essence what I want to do is have a generic interface that itself accepts an interface. the tricky part is that "inner" interface could have a more specific interface layered on top of it.
Here is a representative sample of the structure that I'm trying to build:
public interface IThing { }
public interface IMoreSpecificThing : IThing { }
public interface IWidget<T> where T : IThing { }
public class MySpecificThing : IMoreSpecificThing { }
public class MyWidget : IWidget<MySpecificThing> { }
public class MyClass
{
public IWidget<IThing> MyProperty { get; set; }
public MyClass()
{
MyProperty = new MyWidget();
}
}
The problem is that when I assign MyWidget to MyProperty, I receive the following error:
Cannot implicitly convert type 'MyWidget' to 'IWidget<IThing>'. An
explicit conversion exists (are you missing a cast?)
What am I doing wrong, and is there a way to do this properly?
This would require making your interface covariant:
public interface IWidget<out T> where T : IThing { }
For details, see Covariance and Contravariance in Generics. Note that this does put restrictions on the interface, mainly:
All the type parameters of these interfaces are covariant, so the type parameters are used only for the return types of the members.

Categories

Resources