I confused about a base interface property hiding, what is still needed in the implemented class, can somebody tell me why?
The goal will be the 'EndClass' only hide/override the 'IClassValue Value', and not need to implement the already hide 'IBaseClassValue Value'.
Thanks!
public interface IBaseClassValue { }
public interface IClassValue : IBaseClassValue { }
public class ClassValue : IClassValue { }
//-----------------------------------------
public interface IEndClassBase
{
IBaseClassValue Value { get; set; }
}
public interface IEndClassBaseChild : IEndClassBase
{
new IClassValue Value { get; set; }
}
//-----------------------------------------
public abstract class EndClassAbs<TValue>
{
TValue Value { get; set; }
}
public class EndClass : EndClassAbs<ClassValue>, IEndClassBaseChild
{
public new IClassValue Value { get; set; }
//IBaseClassValue IEndClassBase.Value { get; set; } //-> Why need here the base member while already hide in the 'IEndClassBaseChild' interface
}
If I use somekind of shadow class '_EndClass' then inherit from it, the 'EndClass' could hide/override the 'ClassValue'. I still don't know why this can not do in one step.
public class _EndClass : EndClassAbs<ClassValue>, IEndClassBase
{
public new IBaseClassValue Value { get; set; }
}
public class EndClass : _EndClass, IEndClassBaseChild
{
public new IClassValue Value { get; set; }
}
Related
I'm wanting a class to have a property that is another class, but i want both the outside and inside classes to implement an interface, the outside interface having a property for the one on the inside.
Here's the code I've tried.
interface IMainBody
{
ISubProperty subProperty { get; set; }
}
interface ISubProperty
{
string somethingHere { get; set; }
}
class MainBody : IMainBody // Error CS0738 'MainBody' does not implement interface member 'IMainBody.subProperty'. 'MainBody.subProperty' cannot implement 'IMainBody.subProperty' because it does not have the matching return type of 'ISubProperty'.
{
public SubProperty subProperty { get; set; }
}
class SubProperty : ISubProperty
{
public string somethingHere { get; set; }
}
I know I could use a generic interface like this
interface IMainBody<T>
where T : ISubProperty
{
T subProperty { get; set; }
}
interface ISubProperty
{
string somethingHere { get; set; }
}
But I would prefer not to do this because it means the code will get very messy once there is more than one property like this.
Anyone know of any other workarounds?
class MainBody : IMainBody
{
public SubProperty subProperty { get; set; }
ISubProperty IMainBody.subProperty { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
}
I have an interface (Ae) that has a list of objects (List) from another interface (Ba).
I have a class that implements interface Ae.
I have several classes that implement the Ba interface.
Is there any way to make each class that implements interface Ae has a List of one of the concrete classes that implement Ba as property?
public interface IQuestion
{
IAnswerOption[] Answers { get; set; }
}
public interface IAnswerOption
{
int Id { get; }
bool IsCorrect { get; set; }
}
public class AnswerOptionText : IAnswerOption
{
public int Id { get; }
public bool isCorrect;
public string ansText;
}
public class AnswerOptionImage : IAnswerOption
{
public int Id { get; }
public bool isCorrect;
public string imgSlug;
}
public class AudioQuestion : IQuestion
{
public AnswerOptionImage[] Answers;
public string audioName;
}
public class TextQuestion : IQuestion
{
public AnswerOptionText[] Answers { get; set; }
public string questionText { get; set; }
}
When I try it, AudioQuestion and TextQuestion doesn't allow me to use AnswerOptionImage[] and AnswerOptionText[] respectively.
Visual Studio says that I need to implement interface member IQuestion.Answers, but this is not what I intend.
If someone can help me I would be very grateful. Thanks.
It seems that using generics for your IQuestion interface will be a good fit:
public interface IQuestion<T> where T: IAnswerOption
{
T[] Answers { get; set; }
}
public class AudioQuestion : IQuestion<AnswerOptionImage>
{
public AnswerOptionImage[] Answers{ get; set; }
public string audioName;
}
public class TextQuestion : IQuestion<AnswerOptionText>
{
public AnswerOptionText[] Answers { get; set; }
public string questionText { get; set; }
}
I have following code below. I have two main interfaces IWatch and IWatchService. Oryginally Watch() was in IWatchService and there was no IWatch but since that CollectionService cannot use Watch() method i decided (ISP) to create IWatch interface additionally.In CollectionService i want in ctor pass either DatabaseWatchService or RemoteFilesWatchService therefore i put parameter type in ctor as IWatchService<IEntity> watchService nevertheless when in DoIt() method initialize fileWatcherServiceCsv variable it says:
Cannot implicitly convert type 'RemoteFilesWatchService' to
'IWatchService'. An explicit conversion exists (are you
missing a cast?)
public interface IWatch
{
void Watch();
}
public interface IWatchService<TDataEntity> where TDataEntity : IEntity
{
INotificationFactory NotificationFactory { get; }
ObservableCollection<TDataEntity> MatchingEntries { get; set; }
}
public interface IDatabaseWatchService<TDataEntity> : IWatchService<TDataEntity> where TDataEntity : IDatabaseEntity
{
IDatabaseRepository<IDbManager> DatabaseRepository { get; }
}
public interface IRemoteFilesWatchService<TDataEntity> : IWatchService<TDataEntity> where TDataEntity : IFileEntity
{
List<string> ExistingRemoteFiles { get; set; }
List<RemoteLocation> RemoteLocations { get; set; }
IWinScpOperations RemoteManager { get; set; }
IRemoteFilesRepository<IDbManager, TDataEntity> RemoteFilesRepository { get; }
}
public class RemoteFilesWatchService : IRemoteFilesWatchService<IFileEntity>, IWatch
{
public INotificationFactory NotificationFactory { get; }
public ObservableCollection<IFileEntity> MatchingEntries { get; set; }
public List<string> ExistingRemoteFiles { get; set; }
public List<RemoteLocation> RemoteLocations { get; set; }
public IWinScpOperations RemoteManager { get; set; }
public IRemoteFilesRepository<IDbManager, IFileEntity> RemoteFilesRepository { get; }
public RemoteFilesWatchService(IWinScpOperations remoteOperator,
IRemoteFilesRepository<IDbManager, IFileEntity> remoteFilesRepository,
INotificationFactory notificationFactory)
{
RemoteManager = remoteOperator;
RemoteFilesRepository = remoteFilesRepository; //csv, xml or other repo could be injected
NotificationFactory = notificationFactory;
}
public void Watch()
{
}
}
public class DatabaseWatchService : IDatabaseWatchService<DatabaseQuery>, IWatch
{
public INotificationFactory NotificationFactory { get; }
public ObservableCollection<DatabaseQuery> MatchingEntries { get; set; }
public IDatabaseRepository<IDbManager> DatabaseRepository { get; }
public DatabaseWatchService(IDatabaseRepository<IDbManager> databaseRepository,
INotificationFactory notificationFactory)
{
DatabaseRepository = databaseRepository;
NotificationFactory = notificationFactory;
}
public void Watch()
{
}
}
public class CollectionService
{
private IWatchService<IEntity> _watchService;
public CollectionService(IWatchService<IEntity> watchService)
{
_watchService = watchService;
}
}
class Run
{
void DoIt()
{
IWatchService<IEntity> fileWatcherServiceCsv = new RemoteFilesWatchService(new WinScpOperations(),
new RemoteCsvFilesRepository(new DbManager(ConnectionDbType.MySql)),
new NotificationFactory());
var coll1 = new CollectionService(fileWatcherServiceCsv);
}
}
public interface IEntity
{
}
public interface IFileEntity : IEntity
{
int Id { get; set; }
string Name { get; set; }
bool IsActive { get; set; }
bool RemoveFromSource { get; set; }
string DestinationFolder { get; set; }
RemoteLocation RemoteLocation { get; set; }
}
public interface IDatabaseEntity : IEntity
{
}
public class CsvFile : IFileEntity
{
public int ColumnHeader { get; set; }
public int ColumnsCount { get; set; }
public string Separator { get; set; }
public int ValuesRowStartposition { get; set; }
public int ColumnRowPosition { get; set; }
public int Id { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
public bool RemoveFromSource { get; set; }
public string DestinationFolder { get; set; }
public RemoteLocation RemoteLocation { get; set; }
}
public class XmlFile : IFileEntity
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
public bool RemoveFromSource { get; set; }
public string DestinationFolder { get; set; }
public RemoteLocation RemoteLocation { get; set; }
public string SubNode { get; set; }
public string MainNode { get; set; }
}
This question gets posted almost every day. One more time!
A box of apples is not a box of fruit. Why not?
You can put a banana into a box of fruit, but you cannot put a banana into a box of apples, so a box of apples is not a box of fruit, because the operations you can perform on them are different. Similarly, a box of fruit is not a box of apples.
You're trying to use a IWatchService (box) of IFileEntity (apples) as an IWatchService of IEntity (fruit), and that's not legal.
Now, you might notice that in C# you can use an IEnumerable<Apple> where an IEnumerable<Fruit> is expected. That works just fine because there is no way to put a banana into an IEnumerable<Fruit>. In every member of IEnumerable<T> and IEnumerator<T>, the T comes out, not in.
If you are in that situation then you can mark your interface as
interface IWatchService<out T> ...
And the compiler will verify that every T in the interface is used in "out" positions, and then will allow the conversion you want.
That conversion is called a generic covariant conversion and it only works when:
The generic type is an interface or delegate
The type parameter is marked out, and the compiler verifies that is safe
The varying types (Fruit and Apple, say) are both reference types. You can't do covariant conversions involving int and object, for example.
Your RemoteFilesWatchService implements interface IWatchService<IFileEntity>, while your CollectionService expects a IWatchService<IEntity>. The two types are different, that's why it cannot convert.
Modify your CollectionService to accept IWatchService<IFileEntity> instead, or make RemoteFilesWatchService implement IRemoteFilesWatchService<IEntity>. Or use a non-generic interface in CollectionService instead.
You cannot have a IWatchService<IFileEntity> and treat it as a IWatchService<IEntity>. Compare it to a List<T> for example. You cannot expect to be able to do this:
class Animal {}
class Bird : Animal {}
class Elephant : Animal {}
var birds = new List<Bird>();
// compiler does not allow this...
List<Animal> animals = birds;
// ...because there is no point in adding elephants to a list of birds.
animals.Add(new Elephant());
Making a slight change to take support from variance, should fix your issue as follows:
public interface IEntity
{
}
public interface IFileEntity : IEntity
{
...
}
public interface IWatchService<out TDataEntity> where TDataEntity : IEntity //note the "out" keyword here.
{
}
You can learn more about Variance in Generic Interfaces Here
i need an help on a really easy question about oop .net design.
I've an abstracted class:
public abstract class DataExtractionMethodConfig
{
public abstract DataExtractionMethod DataExtractionMethod { get; }
public object DataExtractionConfig { get; protected set; }
}
where DataExtractionConfig is a simple object that will be used in subclass to contains the configuration details. For example the OdbcExtractionConfig will be
public class OdbcExtractionConfig
{
public string OdbcName { get; set; }
public string BarcodeFilterExpression { get; set; }
public string ConnectionString { get; set; }
public string SqlCommand { get; set; }
public Enum.DatabaseServer DatabaseType { get; set; }
public List<string> KeyColumns { get; set; }
}
and the derived concrete class is
public class OdbcDataExtractionMethod : DataExtractionMethodConfig
{
private OdbcDataExtractionMethod(){}
public OdbcDataExtractionMethod(OdbcExtractionConfig config)
{
this.DataExtractionConfig = config;
}
public override DataExtractionMethod DataExtractionMethod { get { return DataExtractionMethod.ODBC; } }
}
How can i refactor the code to have DataExtractionConfig typed and not a simple object but mantaining the capability to extend the abstract class ?
How can i refactor the code to have DataExtractionConfig typed and not a simple object
By using Generics, but I warn you it can sometimes be a rabbit hole! Meaning that once you start down it, you get deeper and deeper, and things get more and more complex as you go.
public abstract class DataExtractionMethodConfig<T>
{
public abstract DataExtractionMethod DataExtractionMethod { get; }
public T DataExtractionConfig { get; protected set; }
}
And then
public class OdbcDataExtractionMethod : DataExtractionMethodConfig<OdbcExtractionConfig>
{ ... }
Just trying to get my head around this one. Consider the following code.
public class Setting<T> where T: struct
{
public string Name { get; set; }
public T Value { get; set; }
}
public class SettingsDto
{
public List<Setting<>> Settings{ get; set; }
}
The issue is in the SettingsDto class. My Settings property wants me to specify a type for List>. All I know right now is that T must be a struct. How can I create a list of Settings such that I can add to it later - perhaps at runtime. Is there a way around this ?
Many thanks for all replies.
You can carry over the generic parameter over to SettingsDto:
public class SettingsDto<T> where T : struct
{
public List<Setting<T>> Settings { get; set; }
}
You must to pass T generic type to SettingsDto.
Try this:
public class Setting<T> where T: struct
{
public string Name { get; set; }
public T Value { get; set; }
}
public class SettingsDto<T> where T: struct
{
public List<Setting<T>> Settings { get; set; }
}
You can only do it if all settings have something in common. Consider using an interface like this:
public interface ISetting
{
string Name { get; set; }
}
public class Setting<T> : ISetting
where T : struct
{
public string Name { get; set; }
public T Value { get; set; }
}
public class SettingsDto
{
public List<ISetting> Settings { get; set; }
}
class Program
{
static void Main(string[] args)
{
var set=new SettingsDto();
set.Settings=new List<ISetting>();
set.Settings.Add(new Setting<int>() { Name="Setting1", Value=100 });
set.Settings.Add(new Setting<double>() { Name="Setting2", Value=Math.PI });
set.Settings.Add(new Setting<DateTime>() { Name="Setting3", Value=DateTime.Now });
set.Settings.Add(new Setting<int>() { Name="Setting4", Value=200 });
foreach(var setting in set.Settings.OfType<Setting<int>>())
{
Console.WriteLine("{0}={1}", setting.Name, setting.Value);
}
// Setting1=100
// Setting4=200
}
}
Does it has to be struct? Otherwise You could use
public List<Setting<object>> Settings { get; set; }
and cast it when needed.
If it is not for performance reasons, you could put the struct inside a class.