Interface member with "this" keyword - c#

While going through our client's code, I came across below interface in C#, which is having a member with "this" keyword.
public interface ISettings
{
string this[string key] { get; }
}
I am not aware of any such pattern or practice where interface member name starts with "this". To understand more, I checked the implementation of this interface, however still not able to figure out its purpose.
internal class SettingsManager : ISettings
{
public string this[string key]
{
get { return ConfigurationManager.AppSettings[key]; }
}
...
...
}
And here is the caller code:
public static class Utility
{
public static ISettings Handler { get; set; }
public static string Get(string key, string defaultValue)
{
var result = Handler[key];
return Is.EmptyString(result) ? defaultValue : result;
}
}
Unfortunately, I am not able to debug this code to see the things live. But very curious about it. If the implemented code is finally returning a string, then what is the use of "this" keyword out there?

It enables you to do things like:
SettingsManager settings = new SettingsManager();
var setting = settings["my setting"];
A common use is with the List<T> class.
It has the definition:
public class List<T> : IList<T>, ICollection<T>, IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable
{
// ....
public T this[int index] { get; set; }
// ....
}
This allows you to 'index' the internal values in a similar way to an array.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace test
{
static class Program
{
static void Main()
{
List<string> myStrings = new List<string>();
myStrings.Add("abc");
myStrings.Add("def");
Console.WriteLine(myStrings[0]); // outputs: "abc"
Console.WriteLine(myStrings[1]); // outputs: "def"
Console.Read();
}
}
}

They are indexers, allowing to access your class like an array, in the example your provided you see the usage in this line:
var result = Handler[key];

Related

C#, How to pass a List of a Derived class to a method that receives a List of the Base class?

This is a simplified version of my code:
using System.Collections.Generic;
public abstract class FruitBox<T>
{
public T item;
public static T ChooseFirst(List<FruitBox<T>> fruitBoxes)
{
return fruitBoxes[0].item;
}
}
public class Apple
{
}
public class AppleBox : FruitBox<Apple>
{
}
public class FruitShop
{
List<AppleBox> appleBoxes = new List<AppleBox>();
public void Main()
{
AppleBox appleBox = new AppleBox();
appleBoxes.Add(appleBox);
AppleBox.ChooseFirst(appleBoxes); // => Error here
}
}
I have an error in the line:
AppleBox.ChooseFirst(appleBoxes);
cannot convert from System.Collections.Generic.List<AppleBox> to System.Collections.Generic.List<FruitBox<Apple>>
I tried:
AppleBox.ChooseFirst((List<FruitBox<Apple>>)appleBoxes);
But same error.
How do I have to proceed?
The reason for such behaviour is explained here. In short - classes do not support variance in C# and List<AppleBox> is not List<FruitBox<Apple>>.
What you can do:
"convert" collection (actually create a new one):
with OfType<>().ToList()
AppleBox.ChooseFirst(appleBoxes.OfType<FruitBox<Apple>>().ToList())
or just ToList
AppleBox.ChooseFirst(appleBoxes.ToList<FruitBox<Apple>>())
change ChooseFirst signature to work with covariant IEnumerable<out T> interface:
public abstract class FruitBox<T>
{
public T item;
public static T ChooseFirst(IEnumerable<FruitBox<T>> fruitBoxes)
{
return fruitBoxes.First().item;
}
}
You will have to hold the reference of the derived class into the base class variable
List<FruitBox<Apple>> appleBoxes = new List<AppleBox>();
FruitBox<Apple> appleBox = new AppleBox();
appleBoxes.Add(appleBox);
appleBox.ChooseFirst(appleBoxes);

Why cant I expose an implemented interface method?

I've been trying out some n-tier architecture and im really wondering why this code wont compile...
It says the modifier public is not valid for this item. But why not? I need to be able to access the item IRepository.AddString() from a BLL object but it just wont let me make it public....
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
BLL myBLL = new BLL();
}
}
interface IRepository<T>
{
void AddString();
}
interface IStringRepo : IRepository<string>
{
List<string> GetStrings();
}
public class BLL : IStringRepo
{
public List<string> FilterStrings()
{
return new List<string>() { "Hello", "World" };
}
public List<string> IStringRepo.GetStrings()
{
throw new NotImplementedException();
}
public void IRepository<string>.AddString()
{
throw new NotImplementedException();
}
}
}
That's an explicitly-implemented member, which is always private.
Remove IStringRepo. from the declaration to create a normal public member that also implements the interface.
Explicitly implemented interfaces cannot use visibility modifiers.
public List<string> IStringRepo.GetStrings()
should be:
public List<string> GetStrings()

extending classes that must be used in an interface

I have created an interface as shown below. The DTO object is a complex value object with 3 parameters.
public interface IOperation
{
DTO Operate(DTO ArchiveAndPurgeDTO);
}
I need people that impliment this interface to be able to inherit from the original Value object and extend it where required.
My assumption was that they could simply inherit the DTO object, add (for example) another property and use it in the same class that impliments this interface.
When I try to use the extended value object, Visual Studio complains that I am no longer implimenting the interface.
How can I impliment this functionality.
Thanks in advance for any ideas, and/or suggestions.
Gineer
Edit:
DTO Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Company.ArchiveAndPurge
{
public class DTO
{
public DTO(String FriendlyID)
{
friendlyId = FriendlyID;
}
private String friendlyId = String.Empty;
public String FriendlyId
{
get { return friendlyId; }
set { friendlyId = value; }
}
private String internalId = String.Empty;
public String InternalyId
{
get { return internalId; }
set { internalId = value; }
}
private Boolean archivedSuccessfully = false;
public Boolean ArchivedSuccessfully
{
get { return archivedSuccessfully; }
set { archivedSuccessfully = value; }
}
}
}
Extended DTO:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Company.MSO.ArchiveAndPurge
{
public class DTO: Company.ArchiveAndPurge.DTO
{
private Boolean requiresArchiving = true;
public Boolean RequiresArchiving
{
get { return requiresArchiving; }
set { requiresArchiving = value; }
}
}
}
Interface Implementation where VS Complains:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Company.ArchiveAndPurge.Contracts;
using Company.ArchiveAndPurge;
namespace Company.MSO.ArchiveAndPurge
{
public class ResolveFriendlyId: IOperation
{
#region IOperation Members
public DTO Operate(DTO ArchiveAndPurgeDTO)
{
ArchiveAndPurgeDTO.InternalyId = ArchiveAndPurgeDTO.FriendlyId;
return ArchiveAndPurgeDTO;
}
#endregion
}
}
As I understand it, you probably had something like:
public class ExtendedOperation : IOperation
{
public ExtendedDTO Operate(ExtendedDTO dto)
{
...
}
}
That doesn't work in two ways:
You can't change the return type when implementing an interface method
You can't change the parameter list when implementing an interface
In particular, you wouldn't be implementing IOperation in a way which would be compatible with code like this:
IOperation operation = new ExtendedOperation();
operation.Operate(new DTO());
I suspect you might want to make the interface generic:
public interface IOperation<T> where T : DTO
{
T Operate(T dto);
}
Use Generics:
public interface IOperation<T> where T : DTO
{
T Operate(T ArchiveAndPurgeDTO);
}

Type inference question: Generic Method Argument to non-Generic Method

First of all I know that the title is not so good but the thing is I dont even know how to explain my question; I'll just show an example below on what I'm trying to do:
EDIT: I should have given a better example to begin with; let's try again:
// MyAppComponentModel.dll
namespace MyAppComponentModel {
using System.Collections;
interface IResource { }
interface IStringResource : IResource { }
interface IIconResource : IResource { }
interface IDialogResource : IResource { }
interface IResourceProvider {
void GetResource<T>(out T result, IDictionary criteria = null) where T : IResource;
}
}
// ThirdPartyLib.dll
namespace ResourceProviderLibA {
using System.Collections;
using System.ComponentModel.Composition;
using MyAppComponentModel.
public sealed class StringResource : IStringResource { ... }
public sealed class IconResource : IIconResource { ... }
[Export(typeof(IResourceProvider))]
public sealed class StringAndIconResourceProvider : IResourceProvider {
void IResourceProvider.Get<T>(out T result, IDictionary criteria) {
if (typeof(T) == typeof(IDialogResource))
throw new NotSupportedException();
this.InternalGet(out result, criteria);
}
void InternalGet(out IStringResource result, IDictionary criteria) {
result = new StringResource();
...
}
void InternalGet(out IIconResource result, IDictionary criteria) {
result = new IconResource();
...
}
}
}
// MyMefTestApp.exe
namespace MyMefTestApp {
using System.Collections.Generic;
using System.ComponentModel.Composition.Hosting;
using MyAppComponentModel.
static class Program {
[ImportMany(typeof(IResourceProvider))]
private IEnumerable<IResourceProvider> mProviders;
static void Main(String[] args) {
foreach (var provider in this.mProviders) {
...
}
}
}
}
I know it's somehow possible and I strongly believe I did something like this once just dont remember how. Anyone?
I already know that this can be done via Reflection so please skip those solutions - thanks.
This is not possible as T can be anything (the compiler error actually is cannot convert from 'out T' to 'out string'), not just a string or int.
Just expose the privateFoo overloads as public Foo and be done with it, there is no other way as you can't restrict a generic to string or int (both are sealed, and a generic type constraint needs an interface or non sealed class).
edit (changed question)
If your Resource implementation only have parameterless constructors, I would use this (condensed example):
interface IHostProvider
{
void Get<T> (out T result) where T : IHost, new();
}
public interface IHost
{
}
public class Something : IHost
{
}
public class Provider : IHostProvider
{
public void Get<T> (out T result) where T: IHost, new()
{
result = new T();
}
}
If they require parameters however... phew, no idea this late at night. At first I had a static factory method in mind, but as you can't require a static method in an interface nor mark it abstract, this won't work either.
Your sample seems to me impossible. Compiler can infer type arguments of method from known actual parameter types. For example:
void DoSomething<T>(T item)
{
...
}
IFoo foo = default(IFoo);
DoSomething(foo); // void DoSomething<IFoo>(IFoo item);
But compiler can't do opposite. Compiler can't guess T's actual type and that's why it can't select applicable method overload.
void DoSomething(IFoo foo)
{
...
}
T item = default(T);
DoSomething(item); // won't compile unless it is known that T is IFoo (where T : IFoo)

Determine type derivation from generic type

I have the following utility routine which determine whether a type derives from a specific type:
private static bool DerivesFrom(Type rType, Type rDerivedType)
{
while ((rType != null) && ((rType != rDerivedType)))
rType = rType.BaseType;
return (rType == rDerivedType);
}
(actually I don't know whether there is a more convenient way to test the derivation...)
The problem is I want to determine whether a type derives from a generic type, but without specify the generic arguments.
For example I can write:
DerivesFrom(typeof(ClassA), typeof(MyGenericClass<ClassB>))
but what I need is the following
DerivesFrom(typeof(ClassA), typeof(MyGenericClass))
How can I achieve it?
Based on the example of Darin Miritrov, this is a sample application:
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
namespace ConsoleApplication1
{
public class MyGenericClass<T> { }
public class ClassB {}
public class ClassA : MyGenericClass<ClassB> { }
class Program
{
static void Main()
{
bool result = DerivesFrom(typeof(ClassA), typeof(MyGenericClass<>));
Console.WriteLine(result); // prints **false**
}
private static bool DerivesFrom(Type rType, Type rDerivedType)
{
return rType.IsSubclassOf(rDerivedType);
}
}
}
You could leave the generic parameter open:
DerivesFrom(typeof(ClassA), typeof(MyGenericClass<>));
should work. Example:
public class ClassA { }
public class MyGenericClass<T>: ClassA { }
class Program
{
static void Main()
{
var result = DerivesFrom(typeof(MyGenericClass<>), typeof(ClassA));
Console.WriteLine(result); // prints True
}
private static bool DerivesFrom(Type rType, Type rDerivedType)
{
return rType.IsSubclassOf(rDerivedType);
}
}
Also notice the usage of IsSubClassOf method which should simplify your DerivesFrom method and kind of defeat its purpose. There's also the IsAssignableFrom method you may take a look at.

Categories