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.
Related
I have below class structure:
public class FirstContextController : AFirstContextController
public abstract class AFirstContextController : ABaseController<AFirstContextView>
public abstract class ABaseController<TView> where TView : ABaseView
public abstract class AFirstContextView : ABaseContextView
public abstract class ABaseContextView : ABaseView
public abstract class ABaseView : UserControl
Now I create an instance of my controller:
AFirstContextController firstContextController = new FirstContextController();
and need to return it from the method:
public static ABaseController<ABaseContextView> GetContextController( ... )
{
return firstContextController;
}
But then I get an error:
Cannot implicitly convert type 'AFirstContextController' to 'ABaseController'
So I tryied many casting (for example):
return (ABaseController<AFirstContextView>)firstContextController;
return (ABaseController<ABaseContextView>)( (ABaseController<AFirstContextView>)firstContextController );
But still get similar errors according to conversion.
So what conversion should I apply to return it ?
You need an interface derived from ABaseController<ABaseContextView> to make it work.
This has to do with variance and covariance. Reed more about it on MSDN: Covariance and Contravariance in Generics.
You will have to mark the ABaseContextView with out in your interface definition, so the signature should be something like IBaseController<out ABaseContextView>.
Example:
public abstract class ABaseController<TView> : IBaseController<TView> where TView : ABaseView
{
public void SomeMethod() { }
}
And the interface:
public interface IBaseController<out TView> where TView : ABaseView
{
void SomeMethod();
}
Then your current method should read:
public static IBaseController<ABaseContextView> GetContextController( ... )
{
return firstContextController;
}
I've a generic base class where generic type is class and other related inherited class:
public class BaseClass<T> where T : class
{
virtual void DoWork(){..}
virtual void DoAnotherWork(){..}
}
public class SomeInherit<Person> : BaseClass<Person>
{
//...
}
public class OtherInherit<Car> : BaseClass<Car>
{
// override something..
}
Then, I've a BaseClassManager which should be able to load some BaseClass inherited by some co-worker via reflection:
public class BaseClassManager
{
public BaseClass<TItem> LoadBaseClass<T>() where T : BaseClass<???>
{
// how can create an instance of T?
// TItem : class
// T : BaseClass
// -------------> in reality, it should be: T<TItem> (just as BaseClass<Person>)
}
}
Is there any way to accomplish that..?
You need to define a second type parameter for where T : BaseClass<???>.
You can use the new() constraint to allow the method to create instances of a generic type.
public TBaseClass LoadBaseClass<TBaseClass, TItem>()
where TBaseClass : BaseClass<TItem>, new()
where TItem : class
{
return new TBaseClass();
}
Usage:
SomeInherit<Foo> result = LoadBaseClass<SomeInherit<Foo>, Foo>();
Say I have the following three classes/interfaces:
public interface IImportViewModel
{
}
public class TestImportViewModel : IImportViewModel
{
}
public class ValidationResult<TViewModel> where TViewModel : IImportViewModel
{
}
As TestImportViewModel implements IImportViewModel, why will the following not compile?
ValidationResult<IImportViewModel> r = new ValidationResult<TestImportViewModel>();
I understand what the error message "Cannot implicitly convert type 'ValidationResult' to 'ValidationResult'" means. I just don't understand why this is the case. Would this not be covariance?
Would this not be covariance?
Yes, except that in C# 4.0 covariance works on interfaces only. So you will have to make your ValidationResult implement a covariant interface (one for which the generic parameter is defined as out):
public interface IImportViewModel
{
}
public class TestImportViewModel : IImportViewModel
{
}
public interface IValidationResult<out TViewModel> where TViewModel : IImportViewModel
{
}
public class ValidationResult<TViewModel> : IValidationResult<TViewModel> where TViewModel : IImportViewModel
{
}
and now you can do this:
IValidationResult<IImportViewModel> r = new ValidationResult<TestImportViewModel>();
I've written a class that looks like this:
public class MyClass<T>
{
public void doSomething()
{
T.somethingSpecial;
}
}
This code doesn't compile because the compiler has no idea what T is. I would like to constrain T so that it must inherit a certain class that defines somethingSpecial. Bonus points if you can tell me how to do the same thing by contraining T so that it must implement a certain interface.
public class MyClass<T> where T: IAmSomethingSpecial
It's called Constraints on Type Parameters.
Use the following type parameter constraint in the class declaration:
public class MyClass<T> where T : MyBaseClass
You can read more about type parameter contraints for example here at MSDN.
What you want is a generic constraint:
public class MyClass<T> where T : SomeParentClass
You need a Generic Constraint:
public class MyClass<T> where T : ISomeInterface
{
public void doSomething()
{
instanceOfT.somethingSpecial();
}
}
public interface ISomeInterface
{
void DoSomething();
}
public class MyClass<T> where T : ISomeInterface
{
public void doSomething()
{
T.DoSomething();
}
}
The where keyword allows you to specify constraints on the given generic type. You could swap out the interface for a class.
Read the documentation. Generic Constraint.
class MyClass<T> where T : someinterfaceorbaseclassthatTmustinherit
In C#, i have an interface, and there are some class will implement this interface.
i have a generic utility class, which i want to limit so that the utility class can only be declared using types implementing that interface, as show below, how can i do it??
public interface IMyInterface
{}
public class A : IMyInterface {} // can pass into UtilityClass
public interface B : IMyInterface{}
public class C : B {} // can pass into UtilityClass
public class D {} // can Not pass into UtilityClass
public class UtilityClass<T is IMyInterface>
{
// some utility function
}
Thanks.
You're looking for a generic constraint. These are expressed in C# by using the where keyword after the class name.
public class UtilityClass<T> where T:IMyInterface
{
}
public class UtilityClass<T> where T: IMyInterface
{
// some utility function
}
They are called constraints, you can read more here http://msdn.microsoft.com/en-us/library/d5x73970.aspx
use the where clause:
public interface IMyInterface
{}
public class UtilityClass<T> where T : IMyInterface
{
// some utility function
}
You can add restrictions to generic classes like so:
public class UtilityClass<T> where T : IMyInterface
{
// some utility function
}