I wonder if I found the right solution how to access static property/method of the interface when the interface is implemented explicitly.
In .NET 7 interface can define static abstract members. For example System.Numerics.INumberBase interface define:
public static abstract TSelf One { get; }
This interface is explicitly implemented by various numeric types, e.g. System.Int32.
/// <inheritdoc cref="INumberBase{TSelf}.One" />
static int INumberBase<int>.One => One;
Now trying to access int.One value.
Here is what I tried:
using System;
public class Program
{
public static void Main()
{
// Does not compile - because One is implemented explicitly
// Compiler: 'int' does not contain a definition for 'One'
Console.WriteLine(int.One);
// Does not compile
// Compiler: A static virtual or abstract interface member can be accessed only on a type parameter.
Console.WriteLine(System.Numerics.INumberBase<int>.One);
// Compiles
Console.WriteLine(GetOne<int>());
}
private static T GetOne<T>() where T : System.Numerics.INumberBase<T> => T.One;
}
Is the GetOne method the only solution (without using reflection) or am I missing something?
This was discussed in the comments to the proposal for static abstract members in interfaces - currently there are no other options except for the generic indirection (i.e. GetOne<T>() approach) or using reflection for explicitly implemented static abstract interface members.
Just for completeness - using reflection (with not perfect search by member name) approach:
var properties = typeof(int).GetProperties(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
var propertyInfo = properties.FirstOrDefault(t => t.Name.EndsWith(".One"));
var one = (int)propertyInfo.GetValue(null);
Related
I believe this is the only way to achieve what I want but I wanted to put this out there to see if there's a solution that doesn't require using dynamic/reflection.
I have the following hierarchy of types, stripped to the bare essentials to demonstrate the point:
// Validators:
public abstract class Validator<T> { }
public class RequiredValidator<T> : Validator<T> { }
// Fields:
public abstract class Field { }
public abstract class Field<T> : Field
{
public void AddValidator(Validator<T> validator) =>
Console.WriteLine($"Added validator {validator.GetType()}");
}
public sealed class ValueField<T> : Field<T> { }
public sealed class ComputedField<T> : Field<T> { }
...many other field types that inherit Field<T>
This is an example usage of the fluent interface I want to achieve:
ValueField<string> field1 = new ValueField<string>().Required();
The Required() method must be available on all types that inherit Field<T>.
This is what I've come up with:
public static class Extensions
{
public static TField Required<TField, T>(this TField field) where TField : Field<T>
{
field.AddValidator(new RequiredValidator<T>());
return field;
}
public static TField DynamicRequired<TField>(this TField field) where TField : Field
{
DynamicAddRequiredValidator((dynamic)field);
return field;
}
private static void DynamicAddRequiredValidator<T>(Field<T> field)
{
field.AddValidator(new RequiredValidator<T>());
}
}
void Main()
{
// This is desired API usage but results in error:
// The type arguments for method 'Extensions.Required<TField,T>(TField)' cannot be inferred from the usage.
ValueField<string> field1 = new ValueField<string>().Required();
// This works but the user shouldn't have to specify types like this, makes it very annoying to use:
ValueField<string> field2 = new ValueField<string>().Required<ValueField<string>, string>();
// This works but requires dynamic:
ValueField<string> field3 = new ValueField<string>().DynamicRequired();
}
Am I missing a way of achieving this which avoids using dynamic based code?
Generics in C# are an all or nothing. You either pass all, like you've done, or none. It must be designed in a way that all arguments can be inferred. For what you're doing you can just use Field<T> instead of TField<T>, removing that generic type parameter; although it may not be as ideal. There are other ways... Some FLUENT designs return new types that contain the generics as properties allowing you to move forward but your continuation would need the logic of using that continue type as well. It gets a bit confusing but I feel you understand. If not let me know.
It would be nice if the where constraint could also help infer the types but it doesn't. Eric Lippert recently helped me understand that C# tries to infer the generic parameters only and if that can't be inferred it fails. The where constraint is only to limit the generic type to a base and inform developers. Although it does feel like we could also infer based on constraints, since we are basing the types, C# doesn't. Eric has an opinion about not doing so, which I'm sure is more than I understand ATM. Either way, there you have it.
For "extendable" fluent interface, we use following trick in Java (you can try, if it's possible in C# too):
public class Field<L extends Field<L, V>, V> {
public L required() {
//...
return (L) this;
}
}
public class ValueField<V> extends Field<ValueField<V>, V> {
}
Now you can call what you need:
ValueField<String> v = new ValueField<String>().required();
It's thanks to additional type parameter of Field which delegates specific return type of the fluent methods to children.
I would like a technical difference between the following two Extension method declarations and when you would use one over the other:
public static void DoSomething(this MyClass theObject)
vs
public static void DoSomething<T>(this T theObject) where T : MyClass
For example, I know there is a difference when using this with an object of a class that inherits from MyClass class but I don't know why.
Assume this implementation:
public static List<T> DoSomething<T>(this T theObject) where T : MyClass
=> new List<T>();
Invoked as
MyChildClass x; // MyChildClass : MyClass
var list = DoSomething(x);
// list is an instance of List<MyChildClass>, instead of List<MyClass>
Use first (non-generic) when you don't need to know the "actual"
(child) type.
Use second (generic) when you plan to use the "actual" type in
further generic code.
I see it as a "smell" when someone designs a class/function as generic, even though it "doesn't need to be" generic = the base type would suffice. (Equivalent 'generic' impl is somewhat more difficult to read)
In my understanding, if we have some type T1 and a nested type T2 (or a member M2) inside T1, the accessibility of T2 (M2) is the minimum of the accessibility of T1 and T2.
By minimum I mean the accessibility I would get by searching the two accessibility levels in the below schema and taking the one that is lower:
public
|
protected internal
| |
internal protected
| |
(protected AND internal)*
|
private
(* This is not definable directly by an access modifier. It only allows access from inherited types defined inside the assembly.)
Example:
internal class T1
// internal
{
public int i;
// internal
protected class T2
// protected and internal
{
public int j;
// protected and internal
}
}
Is that correct? If not, what are exceptions to this rule?
I'm asking because in the book "Programming in C#: Exam Ref 70-483" by Wouter de Kort there is written:
Something to keep in mind is that the access modifier of the enclosing
type is always taken into account. For example, a public method inside
an internal class has an accessibility of internal. There are
exceptions to this (for example, when an internal class implements a
public interface or when a class overrides a public virtual member of
a base class), so you need to keep track of those things when
determining the accessibility of a type you need.
But there is no further explanation of what that means, and I don't get it.
If an internal class implements a public interface, this class can only be used inside the assembly. So how can the implemented interface methods be more accessible than internal? Does it have something to do with static methods?
If a child class overrides a public method of a base class, the child can only be accessed in its specified level. So how can the overridden method be more accessible if the child is not? Does it have something to do with static methods?
how can the implemented interface methods be more accessible than internal?
Here is the setup: a nested private class implements a public interface.
public interface IVisible {
void CallMe();
}
public class Outer {
private class Hidden : IVisible {
public void CallMe() {
Console.WriteLine("I'm hidden!");
}
}
public static IVisible GetObject() {
return new Hidden();
}
}
The user of this class gain access to CallMe() method of Hidden by virtue of casting it to a public interface IVisible:
IVisible obj = Outer.GetObject();
obj.CallMe(); // prints "I'm hidden!"
how can the overridden method be more accessible if the child is not?
Same setup applies: you make an accessible method that returns an instance of an inaccessible type (Hidden) as an object of its public base class or its public interface (i.e. imagine that IVisible is a class, not an interface).
Essentially, public interface (e.g. IVisible) provides a "window" into a non-public implementation (e.g. Hidden). This is a very powerful technique for controlling access to behavior that you wish to expose.
I'm working on a small class library at work, and it naturally involves using generics for this task. But there is this thing that I don't really understand with generics:
Why would I need to use generic type parameters, and then constrain the the type parameter to a specific base class or interface.
Here's an example to what I mean:
public class MyGenericClass<T> where T : SomeBaseClass
{
private T data;
}
And here's the implementation without generics
public class MyClass
{
private SomeBaseClass data;
}
Are these two definitions the same (if yes, then i don't see the advatage of using generics here)?
If not, what do we benefit from using generics here?
As with almost all uses of generics, the benefit comes to the consumer. Constraining the type gives you the same advantages that you get by strongly typing your parameter (or you can do other things like ensure that there's a public parameterless constructor or ensure that it's either a value or reference type) while still retaining the niceties of generics for the consumer of your class or function.
Using generics also, for example, allows you to obtain the actual type that was specified, if that's of any particular value.
This example is a little contrived, but look at this:
public class BaseClass
{
public void FunctionYouNeed();
}
public class Derived : BaseClass
{
public void OtherFunction();
}
public class MyGenericClass<T> where T: BaseClass
{
public MyGenericClass(T wrappedValue)
{
WrappedValue = wrappedValue;
}
public T WrappedValue { get; set; }
public void Foo()
{
WrappedValue.FunctionYouNeed();
}
}
...
var MyGenericClass bar = new MyGenericClass<Derived>(new Derived());
bar.Foo();
bar.WrappedValue.OtherFunction();
The difference is that the former defines the new class as a specific type; the latter simply defines a plain class with a field of that type.
It's all about type safety. Using generics you can return a concrete type (T) instead of some base type which defines the API you need in your generic class. Therefore, the caller of your method won't have to cast the result to the concrete type (which is an error-prone operation).
The main difference is in usage. In the first case, the usage can have:
MyGenericClass<SomeDerivedClass> Variable
Variable.data.SomeDerivedProperty = X
And so that when you use that class, you can still access anything from SomeDerivedClass without casting back to it.
The second example will not allow this.
MyClass.data = SomeDerivedClassInstance
MyClass.data.SomeDerivedProperty = X //Compile Error
((SomeDerivedClass)MyClass.data).SomeDerivedProperty = X //Ewwwww
You will have to cast back up to the SomeDerivedClass (which is unsafe) to use something specific to the derived class.
I don't think that there is a huge amount of difference except that the generic version is constraining your Class, whereas the second is just a constraint on a member of the class. If you added more members and methods to your first Class, you would have the same constraint in place.
Could somebody kindly explain this to me, in simple words:
there is no way to constrain a type to
have a static method. You cannot, for
example, specify static methods on an
interface.
many thanks in advance to you lovely people :)
With generics, you can add a constraint that means the generic-type supplied must meet a few conditions, for example:
where T : new() - T must have a public parameterless constructor (or be a struct)
where T : class - T must be a reference-type (class / interface / delegate)
where T : struct - T must be a value-type (other than Nullable<TSomethingElse>)
where T : SomeBaseType - T must be inherited from SomeBaseType (or SomeBaseType itself)
where T : ISomeInterface - T must implement ISomeInterface
for example:
public void SomeGenericMethod<T>(T data) where T : IEnumerable {
foreach(var obj in data) {
....
}
}
it is SomeBaseType and ISomeInterface that are interesting here, as they allow you to demand (and use) functions defined on those types - for example, where T : IList gives you access to Add(...) etc. HOWEVER! simply: there is no such mechanism for things like:
constructors with parameters
static methods
operators / conversions
arbitrary methods not defined via a base-type or interface
so: you can't demand those, and you can't use them (except via reflection). For some of those dynamic can be used, though.
so, basically:
public class A{}
public class B{
public static void Foo() {}
}
You can't write a generic constraint for T in:
public class C<T> {}
Such that you restrict to accept only A or B based on the presence or non-presence of the static method Foo().
Imagine the following not working code:
interface IWithStatic
{
void DoIt(); // non-static
static void DoItStatic(); // static
}
class C1 : IWithStatic
{
void DoIt() {} // non-static
static void DoItStatic(){} // static
}
class C2 : IWithStatic
{
void DoIt() {} // non-static
static void DoItStatic(){} // static
}
And, in a program :
IWithStatic myObj = GetWithAnyMethod(); // Return a C1 or C2 instance
myObj.DoIt(); // working, as the runtime type is used (either C1 or C2);
but with the static... how can the compiler interpret this :
IWithStatic.DoItStatic(); // Not knowing which type to use
Do you see what's the problem now ?
It is not possible to have:
public interface IInterface {
static void Method();
}
This is because you are not allowed/able to constrain implementing classes to methods being static.