I was reading about extension methods and how they can extend classes with new methods without having to change the class code definition.
I wanted to know if there was any similar way by which I can add a new data member (like a List or an array) to an existing class and use the data member to store information related to the class?
Yes you can extend that class using inheritence.
public class MyClass
{
...
}
public ExtendedClass: MyClass
{
public int ExtraField {get; set;}
}
This way you have all of the members and methods (except private) that exist on the base.
With extension methods you can only extend the functionality of a class.
What you are looking for can be solved with:
Aggregation OR
Inheritance
This post may help you on deciding which one to use in your case: Inheritance vs. Aggregation
There is no way of directly adding members to a specific class.
If the class isn't sealed, you may extend that class by using inheritance. If it is sealed, you may compose yourself a new class which encapsulates the specific class you wanted to extend and extend the implementation.
For example, if you have MyClass which isn't sealed and you want to extend it, simply inherit:
public class MyExtendedClass : MyClass
{
// Add extra logic
}
or, as for composing a new class yourself, you may do the following:
public class MyExtendedClass
{
private MyClass _class;
public string MyExtraString { get; set; }
}
You can use inheritance or composition for that.
Inheritance Example:
public class Student
{
int age;// all props
}
public class MAStudent : Student // MSStudent is a student with extra stuff.
{
float maAverage;
}
Composition Example:
public class Student
{
int age;// all props
}
public class MAStudent
{
Student student;
float maAverage;
// use student's functions inside the class
}
Inheritance is the easiest way to do things. The problem with it is that it makes your classes coupled.
The good perk with inheritance that you can access every protected+ property \ method.
Although the other answers seem to be correct, the answer to your question IMHO, is that it is not possible to extend an existing class with new properties in the way that extension methods do that. Once a class is defined, you cannot 'add' things to it.
Extension method is an exception, since that is just syntactic sugar for a static helper class.
Also you can write something based on extension methods like this
public class ExistingClass
{
}
public static class ExtendingExistingClass
{
private static Dictionary<ExistingClass,List> _values = new Dictionary<ExistingClass,List>();
public List GetMyNewField(this ExistingClass t)
{
List res = null;
_values.TryGetValue(t, out res);
return res;
}
public void SetMyNewField(this ExistingClass t, List value)
{
_values[t] = value;
}
}
Related
I want to subclass a large number of classes so that they will all contain a certain set of the same properties. What would be the right way to do it in order to avoid repetition? I thought of using generics like:
public class SuperT<T> : T
{
//the same set of properties
}
But the compiler says
Cannot derive from 'T' because it is a type parameter
EDIT: I am trying to subclass some classes in a third party assembly so I cannot use a base class.
For example, the types are "Image", "Label", "Button" etc and I want to subclass them all to contain a property like "Radius". (So that I would use SuperImage element in XAML and when I set it's Radius property from XAML, I will be able to run some certain logic.)
One other way I just thought of right now is using T4 templates. I wonder if there is a way to do this with generics without resorting to templates? I cannot understand why the compiler rejects it.
If these classes all share a common base class or common interface you could write an extension method.
public static class ShapeExetnsionsExtLib
{
public static double Radius(this ShapeBase shape){
return /*calculate radious*/;
}
}
From comments
I am trying to subclass some classes in a third party assembly so I cannot use a base class.
For example, the the types are "Image", "Label", "Button" etc and I want to subclass them all to contain a property like "radius".
Yes they share common base classes but I cannot add anything new to them.
I don't think generics have anything to do with this, however inheritance is probably what you're looking for.
There are two types of inheritance that you can use to subclass, and extension methods work to "superclass"... sort of.
Is-A inheritance
Has-A inheritance
And to simply add a similar method to a bunch of third party objects, you'll use an extension method.
Is-A inheritance
Use a base class if you've got similar method implementations.
public abstract class BaseFoo {
public void Bar() {
// actual code
}
}
public class Foo : BaseFoo
{
}
var foo = new Foo();
foo.Bar();
Use an Interface if you need to implement the same method on each class.
public interface IFoo {
void Bar();
}
public class Foo : IFoo {
public override void Bar(){
// bar implementation
}
}
var foo = new Foo();
foo.Bar();
Combining the two is also allowed, but you can only inherit on base class, where you can inherit multiple interfaces.
Has-A inheritance
This is particularly useful with dependency injection, but it's simply the notion that you have an instance of another class to work with. It's essentially a wrapper class for you to work with.
public class Foo {
private readonly ThirdPartyFoo _tpFoo;
void Foo(ThirdPartyFoo tpFoo) {
_tpFoo = tpFoo;
}
public void Bar(){
// now I can do something with _tpFoo;
_tpFoo.Bar();
}
}
var tpFoo = new ThirdPartyFoo();
var foo = new Foo(tpFoo);
foo.Bar(); // invokes the underlying tpFoo
Lastly, if you just need to add a method to existing classes, then you create an extension method.
public static class ViewExtensions()
{
// this assumes your Image, Button, Label all inherit from View.
public static Whatever Radius(this View view) {
// do your radius work.
}
}
Just Use a base class:
public class Base
{
public int Id { get; set; }
public string Name { get; set; }
}
And inherite from it:
public class A : Base
{
}
public class B : Base
{
}
In general, you want to use one of the answers already posted about using a base class and inheriting from that. However, if the classes are in a third party library and are marked as sealed, then you will need to create a wrapper class to use as a base class.
(Note that this option is a workaround and doesn't truly inherit from the third party class, so things in that class that are marked as protected won't be accessible without a liberal use of reflection.)
// The sealed class within another library
public sealed ThirdPartyClass
{
public ThirdPartyClass(int i) { }
public int SomeProperty { get; set; }
public int SomeMethod(string val) { return 0; }
public static void SomeStaticMethod() { }
}
// The wrapper class to use as a pseudo base class for ThirdPartyClass
public class BaseClass
{
private ThirdPartyClass _obj;
public BaseClass(int i) { _obj = new ThirdPartyClass(i); }
public int SomeProperty
{
get { return _obj.SomeProperty; }
set { _obj.SomeProperty = value; }
}
public int SomeMethod(string val) { return _obj.SomeMethod(val); }
public static SomeStaticMethod() { ThirdPartyClass.SomeStaticMethod(); }
}
// The child class that inherits from the "base" BaseClass
public class ChildClass : BaseClass
{
}
First of all, this might be a logical problem. What if you are going to extend a sealed class? Or Int32 class? Delegate?
Anyway, the way I recommend is to create an interface and implement all the functions you need in the subclass.
I am having 2 classes, both having a same method(name + type +behavior) and a same property (name + type)
public class Country
{
public string Name { get; set; }
public void DisplayName()
{
Console.WriteLine(this.Name);
}
}
public class Person
{
public string Name { get; set; }
public void DisplayName()
{
Console.WriteLine(this.Name);
}
}
-- Person and Country classes are not allowed to inherit
In the above code you can see Person class has similar method(DisplayName) like Country class. I am looking for a way so that both classes can share the same method codes, i want to do this because in my real codes- Method which i want to share is very big and whenever i change code in one class i have to copy paste it in other class too. That i feel is not the correct way.
Please suggest how to resolve this problem.
You say they cannot inherit from a common base class, but you could add an interface, right? I suggest giving them each a common interface. Then define an extension method for that interface. The method will appear for each of them in VS.
(Assumption: this will work if the class members accessed by the extension methods are public or internal.)
interface IDisplayable
{
string Name {get; set;}
}
public class Country : IDisplayable
{
public string Name { get; set; }
}
public class Person : IDisplayable
{
public string Name { get; set; }
}
public static void DisplayName(this iDisplayable d)
{
return doSomeDisplayLogic(d.Name);
}
. . . And in the same class as your extension method, define (not as an extension method) a function doSomeDisplayLogic to do your common logic. (first-time gotcha: make sure the extension method is in the same Namespace or the its namespace is also included in the calling code.)
I don't know if you're new to extension methods or not. They are very powerful. (And like many powerful features, they can be abused). An extension method on an interface seems crazy at first, until you get straight in your head how extension methods really work. LINQ wouldn't work without this!
Update: I see your comment above that the classes can't inherit from a common class, because they are already inheriting from a common class (which I assume can't be messed with too much). I would like to point out an Option 2, based on this: Creating a new class that Country/Person/etc. will inherit from, that itself inherits from the existing common parent class. The existing base class would become a grandparent class, so to speak. This would become more the route to go if Country and Person have other common characteristics besides this DisplayName method. If DisplayName is all you're after, the Interface/Extension pattern might be better.
Define an interface
public interface INameable
{
string Name {get;}
}
then add an extension
public static class INameableExt
{
public static void DisplayName(this INameable n)
{
// do your thing
}
}
I would suggest to avoid Extension Methods in some cases, you can ran into a problem when you need slightly a different implementation for both classes and then you have to design a more generic solution, EM can cause the same issues like multiple inheritance does.
As more generic OOD solution I would suggest to extract this behaviour into a separate service class abstracted by an interface:
public interface IDisplayService()
{
void Display();
}
Then implement it and inject into both classes via constructor.
Also, instead of introducing the interfaces and new classes you can inject Action or Func<> via constructor or even property and then call this method by invoking an injected in delegate.
You could create either a static utility method DisplayName() that you pass the data needed for display, or use composition and move all properties and corresponding methods such as DisplayName() in a separate class - then use an instance of this class from both Country and Person.
You could implement a strategy pattern:
class DisplayNameStrategy<T> {
private readonly Func<T, string> nameSelector;
public void DisplayNameStrategy(Func<T, string> nameSelector) {
this.nameSelector = nameSelector;
}
public void abstract DisplayName(T t);
}
class WriteToConsoleDisplayNameStrategy<T> : DisplayNameStrategy<T> {
public void WriteToConsoleDisplayNameStrategy(Func<T, string> nameSelector)
: base(nameSelector) { }
public override void DisplayName(T t) {
Console.WriteLine(this.nameSelector(t));
}
public class Person {
private readonly DisplayNameStrategy<Person> displayNameStrategy =
new WriteToConsoleDisplayNameStrategy<Person>(x => x.Name);
public string Name { get; set; }
public void DisplayName() {
this.displayNameStrategy(this);
}
}
Note: it's probably better to inject the concrete strategy.
You could use composition: define an interface, a class that implements it, and then have Person and Country implement the interface by calling methods on the implementation class:
// the interface
public interface IName {
string Name { get; set; }
void DisplayName();
}
// a class that implements the interface with actual code
public class NameImpl : IName {
public string Name { get; set; }
public void DisplayName() {
Console.WriteLine(this.Name);
}
}
public class Country : IName {
// instance of the class that actually implements the interface
IName iname = new NameImpl();
// forward calls to implementation
public string Name {
get { return iname.Name; }
set { iname.Name = value; }
}
public void DisplayName() {
// forward calls to implementation
iname.DisplayName();
}
}
What I THINK you are asking for is multiple class inheritance which is not allowed in C#. (but can be with C++ which you are NOT doing).
All the others have identified doing an INTERFACE solution, and probably the best way to go. However, from your description, you have a SINGLE BLOCK of code that is identical regardless of the type of object being a person or a business. And your reference to a huge block of code, you don't want to copy/paste that same exact code among all the other classes that may be intended to use similar common "thing" to be done.
For simple example, you have a functionality that builds out a person's name and address (or business name and address). You have code that is expecting a name and up to 3 address lines, plus a city, state, zip code (or whatever else). So, the formatting of such name/address information is the same for a person vs a business. You don't want to copy this exact method over and over between the two. However, each individual class still has its own things that it is responsible for.
I know its a simple example for context, but I think gets the point across.
The problem with just defining an Interface is that it won't allow you to actually implement the CODE you are referring to.
From your sample, I would consider doing a combination of things.. Create a static class with methods on it that you might want as "globally" available. Allow a parameter to be passed into it of an instance of a class that has a type of interface all the others have expressed that will guarantee the incoming object has all the "pieces" of properties / methods you are expecting, and have IT operate on it as needed. Something like
public interface ITheyHaveInCommon
{
string Name;
string GetOtherValue();
int SomethingElse;
}
public class Person : ITheyHaveInCommon
{
// rest of your delcarations for the required contract elements
// of the ITheyHaveInCommon interface...
}
public class Country : ITheyHaveInCommon
{
// rest of your delcarations for the required contract elements
// of the ITheyHaveInCommon interface...
}
public static class MyGlobalFunctions
{
public static string CommonFunction1( ITheyHaveInCommon incomingParm )
{
// now, you can act on ANY type of control that uses the
// ITheyHaveInCommon interface...
string Test = incomingParm.Name
+ incomingParm.GetOtherValue()
+ incomingParm.SomethingElse.ToString();
// blah blah with whatever else is in your "huge" function
return Test;
}
}
warning: lots of untested code here, wild guessing mostly since i disagree with the base assumption "no inheritance".
something like this should help you. create a new static class and paste your code in here.
public static class Display
{
public static void DisplayName<T>(T obj)
{
if ((T is Person) || (T is Country) || (T is whateveryouwant))
{
//do stuff
}
}
}
in your classes, refactor ShowDisplayName() to call that with "this" as parameter.
...
public void DisplayName()
{
DisplayName(this);
}
...
I wonder why your classes are not allowed to inherit it from a base class, since that's imho the right-est way to solve this.
A couple of options:
Make both classes implement an interface for the common members (Name) and add an extension method for the behaviour (or just a normal static method)
Create methods which take an instance and a lambda exppession to access the comment members, e.g.
public static void Display<T>(T item, Func<T, string> nameGetter)
You'd then call it with (say)
DisplayHelper.Display(person, p => p.Name);
The interface solution is the cleaner one, but using a delegate is more flexible - you don't need to be able to change the classes involved, and you can cope with small variations (e.g. PersonName vs FooName vs Name)
You can define that big method in a separate class and then call the method in both the above classes. For a static method, you can call the method using classname.methodname() syntax.
For a non static method, you will have to do this:
classname obj=new classname();
obj.methodname();
So something like:
public static class StaticClass {}
public class InstanceClass
{
static StaticClass StaticProperty {get;set;}
public InstanceClass()
{
InstanceClass.StaticProperty = StaticClass;
}
}
I thought one could do this but the compiler returns these errors:
static types cannot be used as parameters
static types cannot be used as return types
EDIT: I know that this doesn't work, but why? I imagine StaticClass is stored somewhere in memory, so other variables could be allowed to refer to it at the same memory, right?
EDIT2: One of the use cases would be something like this:
Say you have 5 different static classes you have collected with no source code, and they do generic stuff, so you want to have convenient access to them through a single static class. You could do it like:
public static class GenericStuff
{
public LinearAlgebra LinearAlgebra {get;set;}
public StringUtilities String {get;set;}
public GeometryOps Geometry {get;set;}
}
And use it like:
GenericStuff.LinearAlgebra.GetAngleBetweenVectors(v0, v1);
Some other use cases you could think of.
Update: I am going to use my psychic powers to try and figure what I think you're trying to do.
I'm guessing you have a static class with some methods that you want to access from within another class. Is that right?
Something like this, in other words:
static class HelperMethods
{
public static void SomeHelperMethod();
}
...and what you want to do is something like this?
class SomeOtherClass
{
public void MethodThatUsesHelperMethod()
{
// You want to be able to have "Helper" mean "HelperMethods"?
Helper.SomeHelperMethod();
}
}
If I've interpreted you correctly, there's only one way (that I can think) to sort of accomplish what you're after. This would be to add a using declaration to effectively alias your static type:
// At top of file
using Helper = HelperMethods;
Note that if you do this, you're creating a file-wide alias. There's no way to alias classes at only the class level.
StaticClass is the name of the class. Your StaticProperty property expects an instance of the class, which will never exist because the class is static.
I'm actually surprised you can even have a property typed as a static class, since it represents a total impossibility. (Oh wait, you can't do that; that's what you were saying.)
You say you want to store a "reference to a static class"; I have to assume you mean that you want a reference to the Type object representing the class, in which case you should do this:
public Type StaticProperty { get; set; }
// ...
StaticProperty = typeof(StaticClass);
Static classes are both abstract and sealed (take a peek at the generated IL). So, you can't create an instance of it, and you can't subclass it to have instances of subclasses. That combination alone makes it impossible for you to ever have a reference to an instance of a static class.
Now, to have a reference to the static class work the way you want, you'd have to have metaclasses in C#, or some different kind of aliasing.
To achieve what you want today, you'd have to manually delegate all methods from a wrapper class to the desired static class, or abandon static typing and use dynamic:
public class StaticWrapper : DynamicObject {
Type _type;
public StaticWrapper(Type type) {
_type = type;
}
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) {
var method = _type.GetMethod(binder.Name, BindingFlags.Static | BindingFlags.Public, null, args.Select(a => a.GetType()).ToArray(), null);
if (method == null) return base.TryInvokeMember(binder, args, out result);
result = method.Invoke(null, args);
return true;
}
// also do properties ...
}
Usage:
public static class GenericStuff {
public readonly dynamic LinearAlgebra = new StaticWrapper(typeof(LinearAlgebra));
public readonly dynamic String = new StaticWrapper(typeof(StringUtilities));
public readonly dynamic Geometry = new StaticWrapper(typeof(GeometryOps));
}
Section ยง8.7.12 of the C# specification reads:
Classes that are not intended to be
instantiated, and which contain only
static members should be declared as
static classes. Examples of such
classes are System.Console and
System.Environment. Static classes
are implicitly sealed and have no
instance constructors. Static classes
can be used only with the typeof
operator and to access elements of the
class. In particular, a static class
cannot be used as the type of a
variable or be used as a type argument
Because a static class has no constructors, you can't instantiate it. Because it is sealed you cannot subclass it and create an instance of a subclass. Even if you could subclass it you wouldn't be able to call the base constructor, and therefore you still couldn't instantiate it.
Since you cannot create an object of the type of a static class, it makes no sense to use it as a return type.
Since StaticClass is a type name, not an expression, you cannot pass it as a parameter (in your case, to the property setter). However, you can obtain an instance of the Type class that represents it with the expression typeof(StaticClass).
You cannot store a reference to a static class. You can only store references to instances, and there are no instances of static classes (although static classes may have instance members).
You should take another look at the MSDN page on static classes.
"A static class is basically the same as a non-static class, but there is one difference: a static class cannot be instantiated. In other words, you cannot use the new keyword to create a variable of the class type. Because there is no instance variable, you access the members of a static class by using the class name itself."
I think this is what you are trying to say:
Ok, if you don't want to instantiate it, then your C# needs a bit more tweaking. Assuming your static class implements a property and/or method
public static class StaticClass
{
public static string StaticProperty {get; private set; }
public static void StaticMethod() { //DoSomething }
}
You can forward the property and function definitions in the InstanceClass, notice that you must prefix the class name of the static to the methods/properties that you want to call.
public class InstanceClass
{
private string StaticProperty
{
get { return StaticClass.StaticProperty; }
}
private StaticMethod()
{
StaticClass.StaticMethod();
}
public InstanceClass()
{ }
}
I think that using InstanceClass as a wrapper like this is a bit complicated, and unecessary. I've found that its worth trying to minimize the need for static classes and methods in a codebase. They cause all sorts of headaches when trying to test and debug.
I believe using the namespace feature would be the best way to accomplish what you're trying to do.
LinearAlgebra.cs
namespace GenericStuff
{
public static class LinearAlgebra
{
public static TypeOfResult Function() { ... }
}
}
Strings.cs
namespace GenericStuff
{
public static class Strings
{
public static TypeOfResult Function() { ... }
}
}
Geometry.cs
namespace GenericStuff
{
public static class Geometry
{
public static TypeOfResult Function() { ... }
}
}
All of which can be invoked starting with GenericStuff
var s = GenericStuff.Strings.Random(7);
var identity = GenericStuff.LinearAlgebra.Identity(3);
var square = GenericStuff.Geometry.Square(5);
var area = square.Area();
You can't do this. A class is not an instance of itself. "Dog" is not a Dog. You could assign typeof(StaticClass) to a field of type Type:
static StaticClass StaticProperty {get; set}
InstanceClass.StaticProperty = typeof(StaticClass);
This lets you use reflection on the type.
What I believe the op wants is a way to access other classes easily via a "proxy" that you know of.
So, lets say you have a class called MapHelpers:
public class MapHelper
{
public static string CalculateNearLocation (Vector3 position){...}
}
And you have many other "Helpers" that you don't really remember and just want to have them easily accessible. And so, you want to "store" them inside your "Helpers" class, just so you can remember where you put them.
You can either do this :
public class Helpers
{
public class MapHelpers : MapHelper{}
}
And be able to access your MapHelper via :
Helpers.MapHelpers.CalculateNearLocation(pos)
Or do this :
public partial class Helpers
{
}
public partial class Helpers
{
public class MapHelper
{
public static string CalculateNearLocation (Vector3 position){...}
}
}
And be able to access it via :
Helpers.MapHelper.CalculateNearLocation(pos)
However, the first method, will give you a warning on your IDE (if you have that set) about accessing static methods via derived type.
Depends on what you want to achieve in the end.
If you want to just change one class but not on runtime but on compile time (i.e. the same version of static file is going to be used), then you can easily just configure your app or just make several versions of the same file with various implementations.
Such approach is useful for e.g. translations if you have them in a static files.
This question already has answers here:
Why/when should you use nested classes in .net? Or shouldn't you?
(14 answers)
Closed 10 years ago.
I'm trying to understand about nested classes in C#. I understand that a nested class is a class that is defined within another class, what I don't get is why I would ever need to do this.
A pattern that I particularly like is to combine nested classes with the factory pattern:
public abstract class BankAccount
{
private BankAccount() {} // prevent third-party subclassing.
private sealed class SavingsAccount : BankAccount { ... }
private sealed class ChequingAccount : BankAccount { ... }
public static BankAccount MakeSavingAccount() { ... }
public static BankAccount MakeChequingAccount() { ... }
}
By nesting the classes like this, I make it impossible for third parties to create their own subclasses. I have complete control over all the code that runs in any bankaccount object. And all my subclasses can share implementation details via the base class.
The purpose is typically just to restrict the scope of the nested class. Nested classes compared to normal classes have the additional possibility of the private modifier (as well as protected of course).
Basically, if you only need to use this class from within the "parent" class (in terms of scope), then it is usually appropiate to define it as a nested class. If this class might need to be used from without the assembly/library, then it is usually more convenient to the user to define it as a separate (sibling) class, whether or not there is any conceptual relationship between the two classes. Even though it is technically possible to create a public class nested within a public parent class, this is in my opinion rarely an appropiate thing to implement.
A nested class can have private, protected and protected internal access modifiers along with public and internal.
For example, you are implementing the GetEnumerator() method that returns an IEnumerator<T> object. The consumers wouldn't care about the actual type of the object. All they know about it is that it implements that interface. The class you want to return doesn't have any direct use. You can declare that class as a private nested class and return an instance of it (this is actually how the C# compiler implements iterators):
class MyUselessList : IEnumerable<int> {
// ...
private List<int> internalList;
private class UselessListEnumerator : IEnumerator<int> {
private MyUselessList obj;
public UselessListEnumerator(MyUselessList o) {
obj = o;
}
private int currentIndex = -1;
public int Current {
get { return obj.internalList[currentIndex]; }
}
public bool MoveNext() {
return ++currentIndex < obj.internalList.Count;
}
}
public IEnumerator<int> GetEnumerator() {
return new UselessListEnumerator(this);
}
}
what I don't get is why I would ever need to do this
I think you never need to do this. Given a nested class like this ...
class A
{
//B is used to help implement A
class B
{
...etc...
}
...etc...
}
... you can always move the inner/nested class to global scope, like this ...
class A
{
...etc...
}
//B is used to help implement A
class B
{
...etc...
}
However, when B is only used to help implement A, then making B an inner/nested class has two advantages:
It doesn't pollute the global scope (e.g. client code which can see A doesn't know that the B class even exists)
The methods of B implicitly have access to private members of A; whereas if B weren't nested inside A, B wouldn't be able to access members of A unless those members were internal or public; but then making those members internal or public would expose them to other classes too (not just B); so instead, keep those methods of A private and let B access them by declaring B as a nested class. If you know C++, this is like saying that in C# all nested classes are automatically a 'friend' of the class in which they're contained (and, that declaring a class as nested is the only way to declare friendship in C#, since C# doesn't have a friend keyword).
When I say that B can access private members of A, that's assuming that B has a reference to A; which it often does, since nested classes are often declared like this ...
class A
{
//used to help implement A
class B
{
A m_a;
internal B(A a) { m_a = a; }
...methods of B can access private members of the m_a instance...
}
...etc...
}
... and constructed from a method of A using code like this ...
//create an instance of B, whose implementation can access members of self
B b = new B(this);
You can see an example in Mehrdad's reply.
There is good uses of public nested members too...
Nested classes have access to the private members of the outer class. So a scenario where this is the right way would be when creating a Comparer (ie. implementing the IComparer interface).
In this example, the FirstNameComparer has access to the private _firstName member, which it wouldn't if the class was a separate class...
public class Person
{
private string _firstName;
private string _lastName;
private DateTime _birthday;
//...
public class FirstNameComparer : IComparer<Person>
{
public int Compare(Person x, Person y)
{
return x._firstName.CompareTo(y._firstName);
}
}
}
There are times when it's useful to implement an interface that will be returned from within the class, but the implementation of that interface should be completely hidden from the outside world.
As an example - prior to the addition of yield to C#, one way to implement enumerators was to put the implementation of the enumerator as a private class within a collection. This would provide easy access to the members of the collection, but the outside world would not need/see the details of how this is implemented.
Nested classes are very useful for implementing internal details that should not be exposed. If you use Reflector to check classes like Dictionary<Tkey,TValue> or Hashtable you'll find some examples.
Maybe this is a good example of when to use nested classes?
// ORIGINAL
class ImageCacheSettings { }
class ImageCacheEntry { }
class ImageCache
{
ImageCacheSettings mSettings;
List<ImageCacheEntry> mEntries;
}
And:
// REFACTORED
class ImageCache
{
Settings mSettings;
List<Entry> mEntries;
class Settings {}
class Entry {}
}
PS: I've not taken into account which access modifiers should be applied (private, protected, public, internal)
Suppose I have a class 'Application'. In order to be initialised it takes certain settings in the constructor. Let's also assume that the number of settings is so many that it's compelling to place them in a class of their own.
Compare the following two implementations of this scenario.
Implementation 1:
class Application
{
Application(ApplicationSettings settings)
{
//Do initialisation here
}
}
class ApplicationSettings
{
//Settings related methods and properties here
}
Implementation 2:
class Application
{
Application(Application.Settings settings)
{
//Do initialisation here
}
class Settings
{
//Settings related methods and properties here
}
}
To me, the second approach is very much preferable. It is more readable because it strongly emphasises the relation between the two classes. When I write code to instantiate Application class anywhere, the second approach is going to look prettier.
Now just imagine the Settings class itself in turn had some similarly "related" class and that class in turn did so too. Go only three such levels and the class naming gets out out of hand in the 'non-nested' case. If you nest, however, things still stay elegant.
Despite the above, I've read people saying on StackOverflow that nested classes are justified only if they're not visible to the outside world; that is if they are used only for the internal implementation of the containing class. The commonly cited objection is bloating the size of containing class's source file, but partial classes is the perfect solution for that problem.
My question is, why are we wary of the "publicly exposed" use of nested classes? Are there any other arguments against such use?
I think it's fine. This is basically the builder pattern, and using nested classes works pretty well. It also lets the builder access private members of the outer class, which can be very useful. For instance, you can have a Build method on the builder which calls a private constructor on the outer class which takes an instance of the builder:
public class Outer
{
private Outer(Builder builder)
{
// Copy stuff
}
public class Builder
{
public Outer Build()
{
return new Outer(this);
}
}
}
That ensures that the only way of building an instance of the outer class is via the builder.
I use a pattern very much like this in my C# port of Protocol Buffers.
You can use namespaces to relate things that are... related.
For example:
namespace Diner
{
public class Sandwich
{
public Sandwich(Filling filling) { }
}
public class Filling { }
}
The advantage of this over using classes as if they were namespaces is that you can optionally use using on the calling side to abbreviate things:
using Diner;
...
var sandwich = new Sandwich(new Filling());
If you use the Sandwich class as if it were a namespace for Filling, you have to use the full name Sandwich.Filling to refer to Filling.
And how are you going to sleep at night knowing that?
You might want to check out what Microsoft has to say on the topic. Basically it's a question of style I'd say.
Another practical example that I have for a valid use of public nested classes is in MVC pattern when I use a viewmodel with an IEnumerable property. for example:
public class OrderViewModel
{
public int OrderId{ get; set; }
public IEnumerable<Product> Products{ get; set; }
public class Product {
public string ProductName{ get; set; }
public decimal ProductPrice{ get; set; }
}
}
I use it because I don't want Product class to be re-used outside because it is customized only for that specific viewmodel which contains it. But I can't make it private because the Products property is public.
I primarily use nested classes for fine-tuning access to the nested and/or the container class.
One thing to remember is that a nested class definition is basically a class member, and will have access to all the container's private variables.
You can also use this to control usage of a specific class.
Example:
public abstract class Outer
{
protected class Inner
{
}
}
Now, in this case, the user (of your class) can only access the Inner class, if he implements Outer.
I don't know if this is considered bad design or not, but I've got some search classes I make where a user calls the Run() method, passing in an object that holds search criteria. It then returns a collection of search result objects.
These SearchCriteria and SearchResult classes have no utility outside of using them with the Search class. So I nest them under the Search class to show they go together.
I have to make the nested classes public so the client of the Search class can make the SearchCriteria to pass into the Search class and so they can get the results of the Search.
public class PersonSearch
{
public PersonSearchCriteria
{
string FirstName {get; set;}
string LastName {get; set;}
}
public PersonSearchResult
{
string FirstName {get;}
string MiddleName {get;}
string LastName {get;}
string Quest {get;}
string FavoriteColor {get;}
}
public static List<PersonSearchResult> Run(PersonSearchCriteria criteria)
{
// create a query using the given criteria
// run the query
// return the results
}
}
public class PersonSearchTester
{
public void Test()
{
PersonSearch.PersonSearchCriteria criteria = new PersonSearch.PersonSearchCriteria();
criteria.FirstName = "George";
criteria.LastName = "Washington";
List<PersonSearch.PersonSearchResults> results =
PersonSearch.Run(criteria);
}
}