Reputation: 149
I have a class like below. But I don't know how to inherit it in another class, I need to override a method in this class. I tried many ways but it seems that the parameters TUser and TKey are still in the wrong syntax. How to inherit similar classes?
public class AspNetIdentityUserService<TUser, TKey> : UserServiceBase
where TUser : class, Microsoft.AspNet.Identity.IUser<TKey>, new()
where TKey : IEquatable<TKey>
{
protected readonly Microsoft.AspNet.Identity.UserManager<TUser, TKey> userManager;
protected readonly Func<string, TKey> ConvertSubjectToKey;
public AspNetIdentityUserService(
Microsoft.AspNet.Identity.UserManager<TUser, TKey> userManager,
Func<string, TKey> parseSubject = null)
{
// initilaization
}
//More Methods
}
I tried inheriting like
public class EnforcingLocalSignup<TUser, TKey> :
AspNetIdentityUserService<TUser, TKey> where TUser : class,
Microsoft.AspNet.Identity.IUser<TKey>, new() where TKey : IEquatable<TKey> { }
but it fails with
Error CS7036 There is no argument given that corresponds to the required formal parameter 'userManager' of
'AspNetIdentityUserService<TUser, TKey>.AspNetIdentityUserService(UserManager<TUser, TKey>, Func<string, TKey>)'
Upvotes: 0
Views: 145
Reputation: 2342
When you define a class without defining any constructor, a parameterless constructor is implicitly defined.
Basically this:
public class MyClass { }
Actually is interpreted by the compiler like this:
public class MyClass : System.Object
{
public MyClass() : base() { }
}
This works because System.Object
class has a parameterless constructor, that you can call via base()
.
When a class defines a constructor with parameters but not a parameterless constructor, the compiler won't generate a parameterless constructor, so this code:
public class BaseClass
{
public BaseClass(int parameter)
{
// ...
}
}
Actually is interpreted (and compiled) as:
public class BaseClass : System.Object
{
public BaseClass(int parameter) : base()
{
// ...
}
}
Now, if you inherit from a class that is missing a parameterless constructor without defining a constructor, like this:
public class MyClass : BaseClass { }
What the compiler "sees" is actually this:
public class MyClass : BaseClass
{
public MyClass() : base() { }
}
But BaseClass do not have a constructor that takes no parameters, hence the compilation error. It's easily fixed by either define a parametered constructor in your derived class that matches the constructor of base class:
public class MyClass : BaseClass
{
public MyClass(int parameter) : base(parameter) { }
}
or a parameterless constructor that passes a default value to base constructor:
public class MyClass : BaseClass
{
public MyClass() : base(0) { }
}
depending on your design requirements.
Wrapping up and applying to your case, you can fix with:
public class EnforcingLocalSignup<TUser, TKey> : AspNetIdentityUserService<TUser, TKey>
where TUser : class, Microsoft.AspNet.Identity.IUser<TKey>, new()
where TKey : IEquatable<TKey>
{
public EnforcingLocalSignup(Microsoft.AspNet.Identity.UserManager<TUser, TKey> userManager,
Func<string, TKey> parseSubject = null)
{ }
}
Upvotes: 2
Reputation: 7111
Here's brain dead simple code that repros your error:
public class BaseClass
{
public BaseClass(string userManager)
{
UserManager = userManager;
}
public string UserManager { get; }
}
public class SubClass : BaseClass
{
}
Which results in this error (pointing to the public class SubClass : BaseClass
line):
error CS7036: There is no argument given that corresponds to the required formal parameter 'userManager' of 'BaseClass.BaseClass(string)'
This happens because the base class has no default constructor, only the one that requires a userManager
parameter.
That's the same error you are seeing. Note that it has nothing to do with the complicated generic nature of your classes, only with how the constructors are, um, constructed. Subclass
, since it doesn't define a constructor, gets the default default constructor (i.e., one that just sets all properties to their default values).
If I add a default constructor:
public SubClass () { }
I get the same error, this time pointing to that line of code. However, if I create a constructor like that calls the one-and-only base class constructor:
public SubClass(string userManager) : base (userManager)
{
}
The error goes away.
Upvotes: 3
Reputation: 9804
When inheriting from, towards or between generic classes, you have 3 options for any of the generic parameters:
a) Expose them on the new class as well. Hand them through:
class MySpeciaList<T> : List<T>{
//You propably want to write something additional here
}
Do not that constraints on MySpeciaList<T>
must be at least as restrictive as on the class you inherit from.
b) Hardcode the type. Basically you "de-generezie" the class
class FormList : List<Form> {
//You do not need to add anything here, but maybe want to
//We have to use that trick for XAML, as generics types are not really useable in XAML code
//Note that .NET does have a "Formlist" type, it is from the pre-generic days
}
c) you can of course add generic parameters, that only the new class can use. Indeed you propably do that impicitly:
class SomethingGeneric<T> : object {
//You most definitely should add something here. Ideally something using T
}
All of these can be combined. You can hand through, hardcode and add any number of generic placeholders. Do not that you propably want to use type aliases and var, to keep the code readable.
Upvotes: 2