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);
}
}
Related
I my data access layer I want to use DTOs and make sure that all gateways (table data gateway) will implement method which return List of some DTO specific for given gateway.
To make this happen I have created empty interface like this
public interface IDataTransferObject{}
implemented this interface by all DTOs like this
public class UserAccountTypeDTO : IDataTransferObject
{
public int Id { get; set; }
public int AccountTitle { get; set; }
public int CreditTypeId { get; set; }
public bool Active { get; set; }
}
then I have made generic interface for all my gateways
public interface IDefaultGateway<D> where D:IDataTransferObject
{
List<D> Read(SqlDataReader sqlReader);
}
and finally implemented IDefaultGateway by my gateways
class UserAccountTypeGW : IDefaultGateway<UserAccountTypeDTO>
{
private const string Table = " UserAccountType ";
private string SelectAll = "select * from" + Table + "";
private string SelectById = ...;
public List<UserAccountTypeDTO> Read(SqlDataReader sqlReader)
{
throw new NotImplementedException();
}
}
Is it ok to make empty interfaces just to somehow group classes together even if they don't share any behavior?
Fields in gateways are the same only its values are changing. I did copy and paste for fields to each gateway and I would like to know whether there is faster/lazier way how to do this.
Interface and fields are not friends, therefore it could have been defined as properties. Since there is a need to create constructor in each DTO to initialize properties and also make set private it turns out to be little bit worse than what I did.
Abstract class was pretty much the same as interface
Create base class, define fields and methods and initialize (or override) them in gateway constructor is better in this case or pretty much the same as what have I done?
The word you need to search for is called Marker Interfaces. This is the guideline from MSDN:
AVOID using marker interfaces (interfaces with no members).
If you need to mark a class as having a specific characteristic (marker), in general, use a custom attribute rather than an interface.
Having said that, it is easier to check if a class implements an interface than to check if it has an attribute.
And as #Groo has mentioned in the comment section of this answer, which is a really good point:
Marker interfaces also at least give some compile-time checks, compared to attribute
Regarding the second part of the question (how to avoid code duplication), this is what abstract classes are for.
You can provide some default values which derived classes can override if needed:
abstract class BaseGateway<T> : IDefaultGateway<T> where T : IDataTransferObject
{
readonly string _tableName;
readonly string _selectAll;
public BaseGateway()
{
// default table name
_tableName = this.GetType().Name.Replace("DTO", "");
_selectAll = $"select * from {_tableName}";
}
// these members are virtual, so that they can be overriden
protected virtual string TableName => _tableName;
protected virtual string SelectAll => _selectAll;
// derived classes should implement their own 'Read' method
public abstract List<T> Read(IDataReader sqlReader);
}
However, note that doing stuff like this makes your code prone to SQL injection attacks. It would be a better idea to use an ORM, or at least a "micro" ORM like Dapper.
Dapper gives you this simplicity in a couple of plain IDbConnection extension methods:
public class Dog
{
public int Age { get; set; }
public string Name { get; set; }
}
using (IDbConnection conn = OpenConnection())
{
var dog = conn
.Query<Dog>("Select * from Dog where Age = #Age", new { Age = 10 })
.FirstOrDefault();
}
Avoid using those marker interfaces. The only 'good' reason to use marker interfaces nowadays is if you plan to manipulate certain types of objects using reflection (and it's not a case this time).
In this case - abstract class seems to be the best choice. Define that Read() method inside the abstract class and properties with their default implementation. Override it with virtual method in all the descendants as needed. This way you won't even need a wrapper class for reading every specific type of object, as you will be able to reference that object and call Read() on it directly.
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;
}
}
First of all, it was difficult to find a proper title for my question... sorry in advance for this.
I am facing an issue with C# .NET. I'll try to simplify it with a temporary example.
I have three classes:
book
movie_dvd
game_dvd
each of them have the same base properties such: id and name. We can however suppose they have other different properties and different methods to be the same class. They can of course be children of a parent class to make it better.
Then I create List of each of these classes to define my collection of books, movies and games. Their id property is of course matched with the key of the List, and as I insert each item in the List I give them an appropriate name (their title).
I have a main winForm with 3 buttons: “Show Books Collection”, “Show Movies Collection” and “Show Games Collection”. The user can click one of them, and then another window appear and show the passed collection inside a ListBox (or whatever).
Now here's my problem.
Right now I'm creating three separate (but almost identical) WinForms to display the content of each collection (books, movies, games), which I think is greatly overdoing things. What I would really like to do is create a single window to display the content of any of these collections. The problem is that if I pass a book object/class inside the parameters of the new winForm, on the other side it expects to be a book object.
How can I use a single Winform to display the title of each of these differnt objects without duplicating the WinForm code over and over?
If your form displays the 'common stuff' between the 3 classes - ID, Title, reviews, etc - than you have two choices:
Design a base class that contains these common attributes that each of the other classes can derive from, each possibly overloading and/or modifying the functionality of the base. The form accepts lists of the base class.
Design an interface that defines the base properties and have each of your classes implement it. The form accepts lists of objects that implement the interface.
Both of these solutions are somewhat future-proof too - you can define a 4th kind of thing that inherits or implements accordingly and your form will be none the wiser!
I like #2 better becuase it is great for testing - you can mock up any class that implements your interface and pass it to your form to test it out. No need to test with known-book/dvd/game data!
I'm not a fan of the casting-solutions becuase they're brittle, and tough to extend.
If each of these objects will have the same properties (e.g. Title) then you create a base class with those properties. You could then create more specific properties in the derived classes.
public abstract class MediaBase
{
public String Title { get; set; }
public Int32 Id { get; set; }
}
public sealed class Book : MediaBase
{
public String Author { get; set; }
public Int32 Pages { get; set; }
}
public sealed class MovieDvd : MediaBase
{
public String Director { get; set; }
public Int32 Length { get; set; }
}
public sealed class GameDvd : MediaBase
{
public Int32 NumberOfPlayers { get; set; }
}
Or you could pass the parameters as objects and then cast them back into their actual type.
if (parameter is book)
{
book theBook = ((book)parameter);
}
else if (parameter is movie_dvd)
{
movie_dvd movieDvd = ((movie_dvd)parameter);
}
else if (parameter is game_dvd)
{
game_dvd gameDvd = ((game_dvd)parameter);
}
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();
I have 2 class's
Class 1.
public class BaseContentPage : System.Web.UI.Page
{
}
Class 2.
public class BaseUserControl : System.Web.UI.UserControl
{
}
And now i want them to be aware of this class.
public class BaseCommon
{
public string Variable1 { get; set; }
public string Variable2 { get; set; }
public string Variable3 { get; set; }
}
How I'm currently doing it is by making the variables of the BaseCommon class static like so
public static string Variable1 { get; set; }
public static string Variable2 { get; set; }
public static string Variable3 { get; set; }
How else can i do this?
Use composition.
Give BaseContentPage and BaseUserControl a private field (which can be exposed as a property if needed) of type BaseCommon (don't make it static).
They can either create BaseCommon or have an instance passed in through the constructor (Dependency Injection).
First off, I don't think you want the BaseCommon properties to be static. The properties are then global across the application so changing them from one instance will change them for all instances.
What you're talking about is multiple inheritence and it isn't supported by c#. You'd be better off changing BaseCommon to be an interface and having BaseContentPage and BaseUserControl implement that interface.
If they are static, does that mean that this third class is a global resource? You could look at Singleton or IoC containers or pass the instance to the other classes when constructed.
You need to give more concrete examples of what this common "base" data that you are adding to two different parts of your object inheritance tree are.
Conceivably, say each instance really just has similar data (an example I'm thinking of is internationalization, say, which is used to customize both a page and a usercontrol according to phrase IDs, etc which are specific in context), then what you can do is have a class I18nSettings which implements II18nSettings. Then in each class, encapsulate an I18nSettings instance and implement II18nSettings and pass them through. Alternatively, you can expose the internal I18nSettings instance. I've even just defined an interface and had each class implement it - it was not worth having a separate class at all.
There are other options to do this kind of thing - it depends on whether the concrete classes you are inheriting from implement a lot more useful things than the things you are adding. It might make more sense to inherit from your concrete class and implement other interfaces so that the class can be used in other places.