I'm trying to declare several indexed properties as part of an interface in C#.
The aim being able to write something like:
int v=obj.Field1[4]+obj.Field2[4];
The implementation is done in C++/CLI.
I've found info about the use of a 'proxy' to approach the behaviour in
Named indexed property in C#?
C#:
public interface IMyProp1
{
int this[int idx] { get; }
}
public interface IMyProp2
{
int this[int idx] { get; }
}
public interface IMyThing: IMyProp1, IMyProp2
{
IMyProp1 Field1;
IMyProp2 Field2;
}
In C++/CLI, I've found some info here:
https://msdn.microsoft.com/en-us/library/2f1ec0b1.aspx
But it's not specific about interface
I've written the following (trial and error with the help of the VS2015 compiler)
public ref class MyThing: IMyThing
{
virtual property int default[int]
{
int get(int idx) { return fld1[idx]; }
}
virtual property IMyProp1 Field1 { IMyProp1 get() { return this; } }
virtual property IMyProp2 Field2 { IMyProp2 get() { return this; } }
private:
array<int>^ fld1;
array<int>^ fld2;
}
But I don't see how I can implement 2 different behaviours, as
virtual property int default[int]
is unique. Even if there are 2 'different' interfaces (I concede it's the same signature), I can't figure out a way to specify 2 different implementations:
virtual property int IMyProp1::default[int] { int get(int idx) { return fld1[idx]; }
virtual property int IMyProp2::default[int] { int get(int idx) { return fld2[idx]; }
I've found this information about explicit interface implementation in C++
interface class MyInterface1 { void f(); };
interface class MyInterface2 { void f(); };
ref class MyClass : MyInterface1, MyInterface2
{
public:
virtual void f1() = MyInterface1::f
{
Console::WriteLine("MyClass::f1 == MyInterface1::f");
}
virtual void f2() = MyInterface2::f
{
Console::WriteLine("MyClass::f2 == MyInterface2::f");
}
};
But can't figure out a way to mix that with the indexed property signature.
For explicit implementation of properties, you specify the explicit override on each accessor method.
Try something like:
virtual property int Indexer1[int]
{
int get(int idx) = IMyProp1::default[int]::get { return fld1[idx]; }
}
Related
Hi i'm new in C# console application and i'm using abstract and override but i get stack in the first method in public abstract double Compute() i got an error and it says cannot declare a body because it is marked abstract please help me. thank you!
`
abstract class Cake
{
public string _flavor, _size;
public int _quantity;
public Cake(string flavor, string size, int quantity)
{
_flavor = flavor;
_size = size;
_quantity = quantity;
}
public abstract double Compute()
{
double price;
if(_flavor == "Chocolate" && _size == "Regular")
{
price = 250.50;
}
else if (_flavor == "Chocolate" && _size == "Large")
{
price = 450.50;
}
else if (_flavor == "Strawberry" && _size == "Regular")
{
price = 300.50;
}
else
{
price = 500.75;
}
return price;
}
}
class BirthdayCake:Cake
{
public int _numOfCandles;
public BirthdayCake(string flavor, string size, int quantity, int numOfCandles):base(flavor,size,quantity)
{
_numOfCandles = numOfCandles;
}
public override double Compute()
{
return _numOfCandles * 10.00;
}
}`
Use virtual instead of abstract when you have a default implementation but would like to allow sub-classes to override
As said, you can't declare a body for an abstract function of an abstract class.
You need to create another class herited from your abstract class that declare the body you want.
abstract class Cake
{
public string _flavor, _size;
public int _quantity;
abstract public double Compute();
}
class BirthdayCake : Cake
{
public int _numOfCandles;
public BirthdayCake(string flavor, string size, int quantity, int numOfCandles):base(flavor,size,quantity)
{
_numOfCandles = numOfCandles;
}
public override double Compute()
{
//does your stuff
}
}
abstract class is a class in which you can have functions which are abstract.
abstract function is a function inside an abstract class that has no body and also it forces you to override it in the derived class.
Your issue here is that you wrote an abstract function that has a body.
Fix: Use virtual keyword instead of abstract. virtual don't force you to override the function and you can also have a body in your base class.
(NB: If you are using virtual function instead of abstract function remove the abstract keyword from your class too.)
Abstract methods have no implementation in the same class, so the method definition is followed by a semicolon instead of a normal method block. Derived classes of the abstract class must implement all abstract methods. When an abstract class inherits a virtual method from a base class, the abstract class can override the virtual method with an abstract method. e.g:
Abstract methods have no implementation in the same class-Sample code
public abstract class A
{
public abstract void DoWork(int i);
public String DoWork(String str)
{
return str;
}
}
public class B:A
{
public virtual void DoWork(int i)
{
// here implementation.
}
}
I'm trying to create an interface to a class i have in c++cli which is then consumed in c#.
Basically, I want to do something along the lines of:
public interface class IFoo
{
static int method();
};
public ref class Foo : public IFoo
{
static int method() { return 0; }
};
So obviously this is incorrect, as there will be errors when trying to compile. I've tried numerous different ways, to no avail.
In c#, i would do the following:
public interface IFooCSharp
{
int method();
}
public class FooCSharp : IFooCSharp
{
public static int method() { return 0 };
int IFooSharp.method() { return FooCSharp.method(); }
}
So i was hoping to see if there was an equivalent way to do this in c++cli?
You can't have static members in an interface.
You figured out the right way to do this in C#: through an explicit interface implementation, you just need the right syntax for C++/CLI:
public interface class IFoo
{
int method();
};
public ref class Foo : public IFoo
{
static int method() { return 0; }
virtual int methodInterface() sealed = IFoo::method { return method(); }
};
Unlike in C#, you need to provide a name for your method, even though you don't intend to use it directly.
Here's the syntax for properties:
public interface class IFoo
{
property int prop;
};
public ref class Foo : public IFoo
{
property int propInterface {
virtual int get() sealed = IFoo::prop::get { return 0; }
virtual void set(int value) sealed = IFoo::prop::set { /* whatever */ }
};
};
I have a base class called Message like this:
public abstract class Message
{
protected int m_id;
protected bool m_localized;
protected string m_metaData;
public int GetID() { return m_id; }
public bool GetLocalized() { return m_localized; }
public string GetMetadata() { return m_metaData; }
}
Then, i have two more classes that inherit from Message for example:
public class ClassicMessage : Message
{
private string m_title;
private string m_content;
public void SetTitle(string title) { m_title = title; }
public void SetContent(string content) { m_content = content; }
public string GetTitle() { return m_title; }
public string GetContent() { return m_content; }
}
public class MessageWithCustomContent : Message
{
private List<CustomContent> m_content;
public MessageWithCustomContent()
{
m_content = new List<CustomContent>();
}
public List<CustomContent> GetContent()
{
return m_content;
}
public CustomContent GetContentEntry(int id)
{
return m_content.find(x => x.ID.Equals(id));
}
}
public class CustomContent
{
private int m_id;
public int ID { get; set { m_id = value; } }
private string m_body;
public string Body { get { return m_body; } set { m_body = value; }
private Image m_image;
public Image Image { get { return m_image; } set { m_image = value; } }
}
In a case like this, how can i unify the app interface if the derived classes has similar methods but these methods have different return types? (even when the methods try to do the same)
I know that with the example i'm breaking the Liskov Substitution Principle and the Open/Closed principle, what's the best approach to get around with that?
Thanks for your help!
Edit:
For more clarity, what i'm trying to achieve is to create a common interface to manage all the possible messages as the base "Message", because i want to avoid using typeof in the consumer class.
for example:
if(message is MessageWithCustomContent)
{
// do something with the contents.
}
else if(message is MessageWithCustomContent)
{
// do another thing with the contents.
}
etc...
You could change Message to be generic, and the T would specify the Content return type. See example below.
Edit
You could use a "IMessage" and a "Message: IMessage" as base.
You would then be able to create a IMessage list like so
var messages = new List<IMessage>
{
new ClassicMessage(),
new MessageWithCustomContent()
};
foreach (var message in messages)
{
message.GetContent();
}
Below is how the implementation of IMessagecould be done.
public interface IMessage
{
int GetID();
bool GetLocalized();
string GetMetadata();
object GetContent();
}
public abstract class Message<T> : IMessage
{
protected int m_id;
protected bool m_localized;
protected string m_metaData;
public int GetID() { return m_id; }
public bool GetLocalized() { return m_localized; }
public string GetMetadata() { return m_metaData; }
object IMessage.GetContent()
{
return GetContent();
}
public abstract T GetContent();
}
public class ClassicMessage : Message<string>
{
private string m_title;
private string m_content;
public void SetTitle(string title) { m_title = title; }
public void SetContent(string content) { m_content = content; }
public string GetTitle() { return m_title; }
public override string GetContent()
{
return m_content;
}
}
public class MessageWithCustomContent : Message<List<CustomContent>>
{
private List<CustomContent> m_content;
public MessageWithCustomContent()
{
m_content = new List<CustomContent>();
}
public CustomContent GetCustomContent(int id)
{
return null;
}
public override List<CustomContent> GetContent()
{
return m_content;
}
}
public class CustomContent
{
private int m_id;
public int ID { get; set; }
private string m_body;
public string Body
{
get { return m_body; }
set { m_body = value; }
}
}
I will explain how you break LSP below but before I do that, you are not really doing any inheriting. Yes you are declaring your classes to be inheriting but you are not really inheriting anything. So before learning LSP, perhaps you need to get a grip on inheritance firstly.
How do I know if I am breaking LSP?
Lest say your Message class was like this, notice the virtual and abstract methods:
public abstract class Message
{
protected int m_id;
protected bool m_localized;
protected string m_metaData;
public virtual int GetID() { return m_id; }
public virtual bool GetLocalized() { return m_localized; }
public abstract string GetMetadata();
}
Create a list like this:
var messages = new List<Message>();
Then add concrete types to that list of all the inheriting types. Then do this:
foreach(var thisMessage in messages)
{
var id = thisMessage.GetID();
var loc = GetLocalized();
var meta = GetMetadata();
}
If you get no exception thrown because one of the inheriting classes decided it does not need one of those methods, then you have not broken LSP. The idea is that if something is inheriting Message, then it should inherit everything. Otherwise, we cannot safely and with confidence substitute the inherited one for the parent one.
The reason this principle is important is because there may be existing code which is using Message, as shown in the foreach above, where it is treating all the types polymorphically and a developer decides to inherit it like this:
public abstract class BadMessage
{
public override int GetID()
{
throw new InvalidOperationException
("This method is not needed for BadMessage and should not be called");
}
public override bool GetLocalized() { ... }
public override string GetMetadata() { ... }
}
You see this will break existing code. And the worst part is, the compiler will not even be able to catch it, until it surfaces like an ugly bug in production.
Well, you're missing the interface methods in de base class. Abstract functions, that get implemented in the derivative classes. If you get a Message, not knowing what kind it is, how would you request its contents?
You could add derivative-specific methods to your base, but you'd have to implement an not_implemented exception in a virtual implementation in the base class to compensate for all derivatives not implementing it, and add exception handling. But then you should ask yourself: " is this class really a derivative? What do I want to achieve."
Idea is to have extension method that extend my functionality.
So instead of having something like this:
return Add(Add(storage.GetFirst(), 3), 7);
I want have something like this:
return storage.GetFirst().Add(3).Add(7);
Problem with extension methods is that they have to be static in static class.
This is simplify example of what I want to do.
public class Storage
{
public int GetFirst()
{
return 100;
}
public int GetAll(int x, int y)
{
// ...
return x + y;
}
}
public abstract class MyBase
{
protected Storage storage;
protected MyBase()
{
storage = new Storage();
}
public int Add(int what, int howMuch)
{
return storage.GetAll(what, howMuch);
}
}
public class MyClass : MyBase
{
public int method1()
{
return Add(Add(storage.GetFirst(), 3), 7);
//I want have something like this:
// return storage.GetFirst().Add(3).Add(7);
}
}
Off course classes Storage, MyBase and MyClass must not be static. Logic is simplify to have clean and simple example so relation between classes must stay same.
What I want to do is to make Add method to be extension method, but leave everything else "more less same".
Is this possible to do and how?
An alternative solution would be to make your Storage class actually store something:
public class Storage
{
private int currentValue;
public Storage GetFirst()
{
this.currentValue = 100;
return this;
}
public Storage Add(int toAdd)
{
this.currentValue += toAdd;
return this;
}
public int GetResult()
{
return this.currentValue;
}
}
This way your call would be:
int result = new Storage().GetFirst().Add(3).Add(5).GetResult();
Have one static class for extensions and use something like:
internal static T Map<T> (this int source, Func<int, int, T> function, int extraParam) {
function (source, extraParam);
}
Then you can make your add method something like:
storage.GetFirst ().Map (Add, 3).Map (Add, 7);
Without modifying any of your code, it is possible to achieve what you're trying to do. But your current design makes it hard to do. You should have some storage in Storage class. There is no storage in Storage class despite of its name.
public class StorageValue
{
public StorageValue(Storage storage)
{
this.Storage = storage;
}
public StorageValue(Storage storage, int value)
{
this.Storage = storage;
this.Value = value;
}
public Storage Storage { get; private set; }
public int Value { get; private set; }
public StorageValue GetFirst()
{
return new StorageValue(Storage, Storage.GetFirst());
}
public StorageValue Add(int value)
{
return new StorageValue(Storage, Storage.GetAll(Value, value));
}
public int GetValue()
{
return Value;
}
}
public static class StorageExtensions
{
public static StorageValue ToStorageValue(this Storage storage)
{
return new StorageValue(storage);
}
}
Which these couple of classes, you can call the methods like this
public class MyClass : MyBase
{
public int method1()
{
return storage
.ToStorageValue()
.GetFirst()
.Add(3)
.Add(7)
.GetValue();
}
}
If you want Add, GetFirst to be the extension methods, you may do it now with StorageValue class. But it makes more sense to be in StorageValue class itself.
That said, # Manuel Zelenka's answer is similar to mine which looks better. You may adapt any of them.
I am trying to change the property type in interface implementation class using explicit interface implementation.
interface ISample
{
object Value { get; set; }
}
class SampleA : ISample
{
SomeClass1 Value { get; set; }
object ISample.Value
{
get { return this.Value; }
set { this.Value = (SomeClass1)value; }
}
}
class SampleB : ISample
{
SomeClass2 Value { get; set; }
object ISample.Value
{
get { return this.Value; }
set { this.Value = (SomeClass2)value; }
}
}
class SomeClass1
{
string s1;
string s2;
}
But when I need to pass in interface obj in a function, I cant access the objects of SomeClass1 or SomeClass2.
For eg:
public void MethodA(ISample sample)
{
string str = sample.Value.s1;//doesnt work.How can I access s1 using ISample??
}
I don't know if this is understandable, but I cant seem to get an easier way to explain this. Is there a way to access the properties of SomeClass1 using interface ISample?
Thanks
That is because you've received the object as the interface, so it doesn't know about the class's new property type. You would need to:
public void MethodA(ISample sample)
{
if (sample is SampleA)
{
string str = ((SampleA)sample).Value.s1;
}
}
A better solution might be to use the visitor pattern - which would have implementations for handling the different ISample's.