Access abstract static interface member - c#

How do I get the implemented Name from FooImpl from either the interface IFoo or an instance object?
public interface IFoo {
static abstract string Name { get; }
}
public class FooImpl : IFoo {
public static string Name => "Foo";
}
I can't seem to get the Name value from these methods. Am I missing something? Note that I'd like to access the Name from any implementation of IFoo without knowing the implementation being used. As such, FooImpl.Name would compile and run, but it is not what I'm looking to do directly.
IFoo anImpl = new FooImpl();
Console.WriteLine(anImpl.Name); // [CS0176] Member 'IFoo.Name' cannot be accessed with an instance reference; qualify it with a type name instead
// I know this won't work
Console.WriteLine(IFoo.Name); // [CS8926] A static virtual or abstract interface member can be accessed only on a type parameter.
static string GetName<T>() where T : IFoo
{
return T.Name;
}
// I know this won't work
Console.WriteLine(GetName<IFoo>()); // [CS8920] The interface 'IFoo' cannot be used as type argument. Static member 'IFoo.Name.get' does not have a most specific implementation in the interface.
static string GetName2<T>(T implementation) where T : IFoo
{
return T.Name;
}
Console.WriteLine(GetName2(anImpl)); // [CS8920] The interface 'IFoo' cannot be used as type argument. Static member 'IFoo.Name.get' does not have a most specific implementation in the interface.
I'm not sure what else to try. This post is related but I don't see an answer other than reflection.

Note that I'd like to access the Name from any implementation of IFoo without knowing the implementation being used
Yes, this is impossible (other then with reflection). Static abstract interface members as any other static members belong to type, not to instance so they can be retrieved only via type. You can use the solution from the linked answer or call the GetName "dynamically" i.e. something like:
var fooName = typeof(...).GetMethod(nameof(....GetName))
.MakeGenericMethod(anImpl.GetType())
.Invoke(null, null);
Also you can wrap either of the approaches in some helper and store the processed types values into Dictionary<Type, string> (or ConcurrentDictionary) to mitigate the reflection cost. Or even prebuild the dictionary (depends on the use case).
There is another approach but it requires some changes to the type hierarchy. You can use curiously recurring template pattern (CRTP) + extra method + extra generic interface with default method implementation:
public interface IFoo {
static abstract string Name { get; }
public string GetName();
}
public interface IFoo<T> : IFoo where T : IFoo<T> // CRTP
{
string IFoo.GetName() => T.Name;
}
public class FooImpl : IFoo<FooImpl> {
public static string Name => "Foo";
}
And usage:
IFoo anImpl = new FooImpl();
Console.WriteLine(anImpl.GetName());

You implement it with a read-only property and assign a default value to it.
public interface IFoo {
static abstract string Name { get; }
}
public class FooImpl : IFoo {
public static string Name {get; } = "Foo";
}
Then you read the value where consumed as
public void DoStuff<T>() where T : IFoo
{
string name = T.Name;
}
or specific implementation
public void DoStuff()
{
string name = FooImpl.Name;
}

Related

How to make the interface enforce the implementation not having a setter?

following the example:
interface ISomeInterface
{
string SomeProperty { get; }
}
I have the implementation that compiles:
public class SomeClass : ISomeInterface
{
public string SomeProperty
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
}
which is a problem. How do I make the interface a contract that, won't allow set in it's implementation?
notice: I'm not looking for a solution how to avoid set IN the implementation but in the interface that will validate it from any new implementation, thanks.
Interfaces only specify what MUST be implemented, but do not restrict what other methods, or properties may also be implemented.
So the get is the only thing that you have specified.
Since you are silent on the set, any implementer of the interface is at liberty to add or not to add the set.
In short, with an interface specification you cannot do what you want to do.
If you want to make sure the set is never called then you could always cast the instance to the Interface
If you really need to make sure there is no set you could use an abstract class instead of an interface
abstract class SomeInterface
{
virtual string SomeProperty { get; }
}
Based on Mike answer, you could write something like that :
public interface ISomeInterface
{
string SomeProperty { get; }
}
public abstract class SomeInterfaceBase : ISomeInterface
{
public abstract string SomeProperty { get; }
}
So you can define your class like that:
public class SomeClass : SomeInterfaceBase
{
public override string SomeProperty { get; }
}
If you try to implement a setter, it will not compile.
Having a setter isn't an issue. The reason for this is because of how we treat interfaces.
Whether the concrete class has a setter or not does not matter, because we are supposed to treat the object as an ISomeInterface. In this case it only has a setter.
For instance lets take a factory method:
class Program
{
interface ISomeInterface
{
string SomeProperty { get; }
}
static ISomeInterface CreateSomeClass()
{
return new SomeClass();
}
class SomeClass : ISomeInterface
{
public string SomeProperty
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
}
static void Main(string[] args)
{
ISomeInterface someInterface = CreateSomeClass();
someInterface.SomeProperty = "test"; //Wont compile
}
}
The class's implementation of a setter is meaningless, because we are only interested in treating the object as ISomeInterface. Interfaces are additive. In other words, they define a contract of what needs to be defined, rather than what should not.
If I was to treat it in any other way, it would be something like this:
((SomeClass) someInterface).SomeProperty = "test"; //Code smell
which I would consider a code smell, because it's assuming that someInterface is SomeClass (treating interfaces as concrete classes)

How to specify in C# generics such T that is constructible from string? (generic type constraint)

I want to specify required default constructrion options for my T:
public interface IParameter<T> /* where T : T(string) */ {
T Value { get; set; }
}
so I would be able to construct it from given string if passible like this:
Value = "bla";
or at least like this:
Value = new T("bla");
So how to specify in C# generics such T that is constructible from string?
Unfortunately, that constraint is not legal. Only the parameterless constructor constraint is allowed:
where T : new()
Unfortunately, C# does not offer arbitrary constructor signature restrictions for generic parameters. Only a restricted number of constraints are supported, the closest one of which is the new constraint. However, it serves only for enforcing a parameterless constructor.
You can, however, work around this drawback by working with a factory object that takes a string and returns a T. First, define an interface for such factory objects:
public interface IFactory<T>
{
T Create(string str);
}
Subsequently, you can use that factory type in your interface:
public interface IParameter<TFactory, T>
where TFactory : IFactory<T>
{
T Value { get; set; }
}
If you want to be able to instantiate the factories at will, you can require them to have a parameterless constructor:
public interface IParameter<TFactory, T>
where TFactory : new(), IFactory<T>
{
T Value { get; set; }
}
Then, you could use a generic method to instantiate a T based on a string, e.g. as an extension method for your interface:
public static class ParameterUtilities
{
public static void AssignValue<TFactory, T>(this IParameter<TFactory, T> prm, string str)
where TFactory : new(), IFactory<T>
{
var factory = new TFactory();
prm.Value = factory.Create(str);
}
}
As an example of how to use this, let's assume the variable myPrm is an instance of that implements your IParameter interface with appropriate type arguments. You can then invoke something like this:
myPrm.AssignValue("Hello, World!");
You can't, because in generic type constraints you can't say that the type must have a specific constructor (only that it must have a parameterless constructor) nor say that it must have specific methods/operators.
BUT
public interface IFromString<T>
{
void DeserializeFromString(string str);
}
public class MyType : IFromString<MyType>
{
public int Value;
public void DeserializeFromString(string str)
{
Value = int.Parse(str);
}
}
public interface IParameter<T> where T : IFromString<T>, new()
{
T Value { get; set; }
}
public class Parameter<T> : IParameter<T> where T : IFromString<T>, new()
{
T Value { get; set; }
public void Load(string str)
{
Value = new T();
Value.DeserializeFromString(str);
}
}
A classical example... an interface that says that a type can be deserialized from (something) (xml very often :-) )
Use:
Parameter<MyType> parameter = new Parameter<MyType>();
parameter.Load(someStringLoadedFromSomewhere);
You can't specify a constructor in an interface. Depending on your requirements you could use an abstract class:
Pseudo code as not at machine with VS:
public abstract class BaseParameter<T>
{
public abstract void BaseParameter(string something);
T Value { get; set; }
}

Is it possible to impose a type constraint on List<Interface>?

In My class I have
class MyClass : IMyInterface
{
//I want MyClass only to be able to accept object of type List<SomethingElse>
public List<ISomething> ListOfSomethings {get; set;}
}
interface IMyInterface{
List<ISomething> ListOfSomethings {get; set;}
}
class SomethingElse : ISomething{
}
class SomethingMore : Isomething{
}
Basically I want to know if it is possible to constrain the type that the list uses in MyClass, so if someone tried coding it to the wrong type (i.e. a List of SomethingMore) it would throw an exception.
EDIT: If this is not possible to do, is there an alternative solution that would work?
You can constrain the T (type) of the list items (and any other T) by using the where restriction:
for more details see Constraints on Type Parameters
Interfaces:
interface ISomething { }
Allows to only use Ts that implement the interface ISomething.
interface IMyInterface<T> where T : ISomething
{
List<T> ListOfSomethings { get; set; }
}
Classes:
class SomethingElse : ISomething { }
class SomethingMore : ISomething { }
class MyClass1 : IMyInterface<SomethingElse>
{
public List<SomethingElse> ListOfSomethings { get; set; }
}
class MyClass2 : IMyInterface<SomethingMore>
{
public List<SomethingMore> ListOfSomethings { get; set; }
}
You can restrict the T whereever it suits you. Here for example on the class itself.
This allows only SomethingElse
class MyClass3<T> : IMyInterface<T> where T : SomethingElse
{
public List<T> ListOfSomethings { get; set; }
}
an example with a Dictionary:
var dic = new Dictionary<string, IMyInterface<ISomething>>();
dic.Add("MyClass1", (IMyInterface<ISomething>)new MyClass1());
dic.Add("MyClass2", (IMyInterface<ISomething>)new MyClass2());
if you won't cast it everytime then the only solution that I can currently think of is to create your custom dictionary and encapsulate the casting:
class MyDictionary : Dictionary<string, IMyInterface<ISomething>>
{
public void Add(string key, MyClass1 value)
{
base.Add(key, (IMyInterface<ISomething>)value);
}
public void Add(string key, MyClass2 value)
{
base.Add(key, (IMyInterface<ISomething>)value);
}
}
var dic2 = new MyDictionary();
dic2.Add("MyClass1", new MyClass1());
dic2.Add("MyClass2", new MyClass2());
//I want MyClass only to be able to accept object of type List<SomethingElse>
Then you can't define it as List<ISomething>, but rather use a different interface or even a concrete type. If you define it as List<ISomething>, than it automatically accepts anything, that implements ISomething interface. There's no way around that.
C# is a typesafe by language design, so there is no way the consumer of your list can inject into it a type which is not SomethingElse or SomethingMore.
If you need to constrain to some of types derived from common interface, like SomethingElse, I would go
Hide a property that exposes a List itself
private List<ISomething> ListOfSomethings {get; set;}
Add a public member function, say FromList
public void FromList(List<SomethingElse> somethings)
{
ListOfSomethings = somethings;
}
This function becomes the only way to assign a list to a class, and considering that it accepts only lists of certain type, you are created desired limitation.
You can do this using explicit interface implementation:
class MyClass : IMyInterface
{
List<ISomething> IMyInterface.ListOfSomethings
{
get { return this.ListOfSomethings.Cast<ISomething>().ToList(); }
set { this.ListOfSomethings = value.Cast<SomethingMore>().ToList(); }
}
List<SomethingMore> ListOfSomethings { get; set; }
}
Please note that it is not recommended to make such a restriction, because this violates the Liskov substitution principle: The user of your class might be using the IMyInterface interface and has no idea that its type is restricted.
Another problem is exposing a List<T> like this in an interface: The caller can either call list methods like Add or Remove or set the entire List instance. This is probably not what you want. If you want to expose a readonly collection, use a getter with an array or enumerable type.

Is there any way an interface can cause different behavior?

Say I have the following code:
class Foo: IFoo {
public string fooProp { get; set; }
}
interface IFoo {
string fooProp {get; set; }
}
Is it at all possible for there to be different behavior between:
Foo x = new Foo();
someMethod(x);
and:
IFoo x = new Foo();
someMethod(x);
?
I think it may differ. If somebody's used bad style of programming, i.e.:
public void someMethod(IFoo f)
{
if (f is Foo)
{
Foo f1 = (Foo)f;
//Do smth with unique Foo members
}
//Do anything with IFoo members
}
Yes, there is a difference if someMethod has different overloads for IFoo and Foo.
public void someMethod(Foo f)
{
// Overload 1
}
public void someMethod(IFoo f)
{
// Overload 2
}
Foo x = new Foo();
someMethod(x); // Matches overload 1
IFoo x = new Foo();
someMethod(x); // Matches overload 2
(I'm no expert) but in your first scenario, you would get access to everything in Class Foo. In the second scenario, you would only be able to access the IFoo members. So if Foo has additional methods (that aren't part of the interface), you will be able to access them in your first scenario but not the second.
I believe using the interface name instead of the class name is just another way to encapsulate data and only provide access to the interface members. For instance you could have Foo and Bar which both implements IFoo. You could add both of them to, say, a List.
There would never be any difference.
Remember, an interface is a contract. By deriving Foo from IFoo, you are implementing that contract.
In both cases, because Foo is an IFoo and adheres to the contract, the behaviour will always be the same.
Of course, how Foo implements that contract is anybodies guess. But the contract is adhered too by the signature of the interface.
If you have two interfaces and there is a common method name in each of them then the implementing class can implement the same method differently. The it depends how the method is called - via interface or not and via which interface.
See here for a similar question:
Inheritance from multiple interfaces with the same method name
Different bahavior can be, but inside someMethod.
Say you have
class Foo: IFoo {
public fooProp { get; set; }
}
interface IFoo {
fooProp {get; set; }
myCustomProp {get;set}
}
if you have
public void someMethod(Foo _foo){
_foo.myCustomProp; //CAN DO THIS, AS YOUR TYPE IS _FOO_
}
Which will not be possible to do in case when the parameter of the method is defined like.
public void someMethod(IFoo _foo){
_foo.myCustomProp; //NO SUCH METHOD INFO
}
unless you don't cast. So the difference is that decaring IFoo, to decalre generic access parameter, but get less "potential" in terms of data access, but get a huge potential in abstraction over types in your architecture.
So the difference will be only in regard of architecture and program workflow.
You could have an explicitly implemented interface in Foo.
class Foo: IFoo {
private string _fooprop;
private string _ifooprop;
public string fooProp
{
get {return "IFoo";}
set {_fooprop=value;}
}
string IFoo.fooProp
{
get {return "Foo";}
set {_ifooprop=value;}
}
}
interface IFoo {
string fooProp {get; set; }
}
with this, you will have:
IFoo foo1=new Foo();
Foo foo2=new Foo();
Console.WriteLine(foo1.fooProp); // Foo
Console.WriteLine(foo2.fooProp); // iFoo
It's possible if you explicitly implement IFoo:
public class Foo : IFoo
{
public string Prop
{
get { return "Hello Foo"; }
}
string IFoo.Prop
{
get { return "Hello IFoo"; }
}
}
public static void SomeMethod<T>(T foo) where T : IFoo
{
var prop = typeof(T).GetProperty("Prop");
Console.WriteLine(prop.GetValue(foo));
}

Java Inheritance Constraints

I am trying to port some code I wrote in C# to Java, but do not know all of the Java syntax yet. I also have no idea what this type of thing is called, so it is harder to search..I am calling it "inheritance constraints."
Basically, is there a java equivalent to this C# code:
public abstract class MyObj<T> where T : MyObj<T>, new()
{
}
Thanks.
Edit:
Is there any way to do this:
public abstract class MyObj<T extends MyObj<T>> {
public abstract String GetName();
public virtual void Test() {
T t = new T(); // Somehow instantiate T to call GetName()?
String name = t.GetName();
}
}
Not quite. There's this:
public abstract class MyObj<T extends MyObj<T>>
but there's no equivalent to the new() constraint.
EDIT: To create an instance of T, you'll need the appropriate Class<T> - otherwise type erasure will byte you.
Typically you'd add this as a constructor parameter:
public MyObj(Class<T> clazz) {
// This can throw all kinds of things, which you need to catch here or
// propagate.
T t = clazz.newInstance();
}
Judging by your comment above, you're looking for the following construct:
An interface with which you will interact with MyObj objects in code... you will be calling the test() method (standard style in Java is camelcase methods, capitalized classes/interfaces)
public interface IMyObj {
public void test();
}
You will want the abstract superclass... for the example that you've chosen, you don't NEED to specify any genericism, although you absolutely can if the actual implementation is more reliant on type safety... this class should implement the IMyObj interface:
public abstract class MyObj implements IMyObj {
String name;
public abstract String getName();
public void test() {
name = getName();
}
}
From here you would write your subclasses to MyObj...
public class MySubObj1 extends MyObj {
public String getName() { return "MySubObj1"; }
}
public class MySubObj2 extends MyObj {
public String getName() { return "MySubObj2"; }
}
Then you safely and correctly use the following snippet in another class:
IMyObj obj = new MySubObj1();
obj.test();
The key is that you use interfaces to hide the implementation, and use abstract classes to hold common code that subclasses will utilize in their implementations.
Hope this helps!

Categories

Resources