Static implicit operator - c#

I recently found this code:
public static implicit operator XElement(XmlBase xmlBase)
{
return xmlBase.Xml;
}
What does static implicit operator mean?

This is a conversion operator. It means that you can write this code:
XmlBase myBase = new XmlBase();
XElement myElement = myBase;
And the compiler won't complain! At runtime, the conversion operator will be executed - passing myBase in as the argument, and returning a valid XElement as the result.
It's a way for you as a developer to tell the compiler:
"even though these look like two totally unrelated types, there is actually a way to convert from one to the other; just let me handle the logic for how to do it."

Such an implicit operator means you can convert XmlBase to XElement implicitly.
XmlBase xmlBase = WhatEverGetTheXmlBase();
XElement xelement = xmlBase;
//no explicit convert here like: XElement xelement = (XElement)xmlBase;

Another interesting usage is (which Unity did to check if an object (and therefore an instance of MonoBehavior) is null):
public static implicit operator bool (CustomClass c)
{
return c != null;
}
Note that the code has to be inside the class (CustomClass in this case). That way you can do something like this:
void Method ()
{
CustomClass c1 = null;
CustomClass c2 = new CustomClass ();
bool b1 = c1; // is false
bool b2 = c2; // is true
if (!c1 && c2)
{
// Do stuff
}
}
Obviously the most notorious use might be using it to convert one of your classes to another of your classes. But using them with basic types is worth a consideration as well... and I see it mentioned quite rarely.

It's an implicit conversion operator (as opposed to an Explicit operator, which requires the (type) conversion syntax)

My two cents.
This is useful in Unit testing an immutable entity to be used with Builder Pattern.
Say you have Employee domain object defined in an immutable way. We do this typically when want to adhere to DDD style.
public class Employee
{
public Employee(int id, string firstname, string lastname, DateTime birthdate, string street)
{
this.ID = id;
this.FirstName = firstname;
this.LastName = lastname;
this.BirthDate = birthdate;
this.Street = street;
}
public int ID { get; private set; }
public string FirstName { get; private set; }
public string LastName { get; private set; }
public DateTime BirthDate { get; private set; }
public string Street { get; private set; }
public string getFullName()
{
return this.FirstName + " " + this.LastName;
}
public int getAge()
{
DateTime today = DateTime.Today;
int age = today.Year - BirthDate.Year;
if (BirthDate > today.AddYears(-age))
age--;
return age;
}
}
Now you can have an employee builder like the following(inside of the test project). Notice in the end, we have this implicit operator.
public class EmployeeBuilder
{
private int id = 1;
private string firstname = "first";
private string lastname = "last";
private DateTime birthdate = DateTime.Today;
private string street = "street";
public Employee Build()
{
return new Employee(id, firstname, lastname, birthdate, street);
}
public EmployeeBuilder WithFirstName(string firstname)
{
this.firstname = firstname;
return this;
}
public EmployeeBuilder WithLastName(string lastname)
{
this.lastname = lastname;
return this;
}
public EmployeeBuilder WithBirthDate(DateTime birthdate)
{
this.birthdate = birthdate;
return this;
}
public EmployeeBuilder WithStreet(string street)
{
this.street = street;
return this;
}
public static implicit operator Employee(EmployeeBuilder instance)
{
return instance.Build();
}
}
Now you can have a employee test class like the following.
public class EmployeeTest
{
[Test]
public void GetFullNameReturnsCombination()
{
// Arrange
Employee emp = new EmployeeBuilder().WithFirstName("Vivek").WithLastName("Koppula");
// Act
string fullname = emp.getFullName();
// Assert
Assert.That(fullname, Is.EqualTo("Vivek Koppula"));
}
[Test]
public void GetAgeReturnsCorrectValue() {
// Arrange
Employee emp = new EmployeeBuilder().WithBirthDate(new DateTime(1983, 1,1));
// Act
int age = emp.getAge();
// Assert
Assert.That(age, Is.EqualTo(DateTime.Today.Year - 1983));
}
}
This makes writing unit tests easier by enabling us to construct the employee just with required parameters.
For example in the first test, we are only concerned with first name and last name. So for the first case, we don't have to be bothered by age and street.
Similarly for the second case, we are concerned with age and nothing else.
Article References.
flexible-and-expressive-unit-tests-with-the-builder-pattern
improve-tests-with-the-builder-pattern-for-test-data

Related

NSubstitute: Difference between Substitute.For<> and Substitute.ForPartsOf

I'm using NSubstitute. I have to fake a class and cannot dig out the difference of Substitute.For<...>() and Substitute.ForPartsOf<...>. I already read the documentation but don`t get the point, where the two behave different.
Substitute.For<>() creates full mock, while Substitute.ForPartsOf<> creates partial mock. For example:
[Test]
public void Test()
{
var person = Substitute.For<Person>();
person.GetAge().Returns(20);
var age = person.GetAge(); //returns 20
var name = person.GetName(); //returns empty string
var partialPerson = Substitute.ForPartsOf<Person>();
partialPerson.GetAge().Returns(20);
var age2 = partialPerson.GetAge(); //returns 20
var name2 = partialPerson.GetName(); //returns John
}
public class Person
{
public string Name { get; } = "John";
public int Age { get; } = 10;
public virtual int GetAge()
{
return Age;
}
public virtual string GetName()
{
return Name;
}
}
Generally ForPartsOf<> will use concrete implementation if it has not been substituted.

Want to create multiple objects of a class at runtime

I am a complete fresher I have been told to create a class for Candidate ..
after creating the database for the module. What I have created is
public class Class1
{
public class JobHistory
{
public string CompName, Tech, Profile;
public string StartDate;
public string EndtDate;
public int CurrentAnnualSalary;
public void AddNew(string CompName, string Tech, string Profile,
string StartDate, string EndtDate,
int CurrentAnnualSalary)
{
this.CompName = CompName;
this.Tech = Tech;
this.Profile = Profile;
this.StartDate = StartDate;
this.EndtDate = EndtDate;
this.CurrentAnnualSalary = CurrentAnnualSalary;
}
}
public class PersonalInformation
{
public string FirstName, LastName, DateOfBirth, PhoneNo1, PhoneNo2;
public string EmailId;
public int TotalExperienceInMonths;
public void AddNew(string FirstName, string LastName, string DateOfBirth,
string PhoneNo1, string PhoneNo2,
int TotalExperienceInMonths, string EmailId)
{
this.FirstName = FirstName;
this.LastName = LastName;
this.DateOfBirth = DateOfBirth;
this.PhoneNo1 = PhoneNo1;
this.PhoneNo2 = PhoneNo2;
this.EmailId = EmailId;
this.TotalExperienceInMonths = TotalExperienceInMonths;
}
}
public class Skills
{
int SkillId;
string Skill;
}
public class Candidate
{
int CandidateId;
JobHistory jh1 = new JobHistory();
PersonalInformation pi = new PersonalInformation();
public void AddNew(int CandidateId,JobHistory jh2,PersonalInformation pi2)
{
this.CandidateId = CandidateId;
this.jh1.AddNew(jh2.CompName, jh2.Tech, jh2.Profile,
jh2.StartDate, jh2.EndtDate,
jh2.CurrentAnnualSalary);
this.pi.AddNew(pi2.FirstName, pi2.LastName, pi2.DateOfBirth,
pi2.PhoneNo1, pi2.PhoneNo2,
pi2.TotalExperienceInMonths, pi2.EmailId);
}
public void UpdateExisting();
public void Delete();
}
}
here I wanted to another class of Skills.
But from the frond end the candidate will have multiple skills and he will update them. So for that I wanted the objects of class skills to be created at the runtime so should I be using the List<>? How to go ahead? Am I correct till now?
As #Jon skeet mentioned you need to use the Constructor and you need to remove the class1 nested class rarely required.
Start with writing constructor for your classes in place of AddNew method like below
public class JobHistory
{
public string CompName, Tech, Profile;
public string StartDate;
public string EndtDate;
public int CurrentAnnualSalary;
public JobHistory(string CompName, string Tech, string Profile,
string StartDate, string EndtDate,
int CurrentAnnualSalary)
{
this.CompName = CompName;
this.Tech = Tech;
this.Profile = Profile;
this.StartDate = StartDate;
this.EndtDate = EndtDate;
this.CurrentAnnualSalary = CurrentAnnualSalary;
}
//If required then you can also need write out the empty constructor
public JobHistory(){}
}
You can also change your class1 into the namespace so your classes can stay in same namespace. More info on namespace
namespace StudeProfileProject
And one more thing, If you are declaring the properties as public then use the getters and setters at the time of declaration so your final class will be look like,
public class JobHistory
{
public string CompName{get;set}
public string Tech {get;set;}
public string Profile{get;set;}
//More properties ....
public JobHistory()
{}
public JobHistory(string CompName, string Tech, string Profile,
string StartDate, string EndtDate,
int CurrentAnnualSalary)
{
this.CompName = CompName;
this.Tech = Tech;
this.Profile = Profile;
this.StartDate = StartDate;
this.EndtDate = EndtDate;
this.CurrentAnnualSalary = CurrentAnnualSalary;
}
}
If you want multiple skills for each Candidate then List will be good option and you can declare it in the your Candidate class
public class Candidate
{
int CandidateId;
JobHistory jh1 = new JobHistory();
PersonalInformation pi = new PersonalInformation();
List<Skill> CandidateSkills = new List<Skills>();
public Candidate(int CandidateId,JobHistory jh2,PersonalInformation pi2)
{
this.CandidateId = CandidateId;
this.jh1= new JobHistory (jh2.CompName, jh2.Tech, jh2.Profile,
jh2.StartDate, jh2.EndtDate,
jh2.CurrentAnnualSalary);
this.pi = new PersonalInformation (pi2.FirstName, pi2.LastName, pi2.DateOfBirth,
pi2.PhoneNo1, pi2.PhoneNo2,
pi2.TotalExperienceInMonths, pi2.EmailId);
}
public void UpdateExisting();
public void Delete();
}
And you will be able to use all the Collection methods for your need. Here is more info on it.
First, you could replace the AddNew-Methods with Constructors.
For your Candidate class it could look like this:
public Candidate(int CandidateId,JobHistory jh2,PersonalInformation pi2)
Using a List<Skill> is a good idea. You can then use the Add-Method to add a skill.

Calling a class method dynamically

Edit: In real life i don't have a Book class. This is just an example to be clear. Real problem really needs reflection to solve it.
Suppose that I have some classes:
Book, Apple, Door.
class Book
{
...
public decimal getPrice()
{...}
public string getTitle()
{...}
public decimal getAuthor()
{...}
}
and something same for other classes.
May i call a class method dynamically from a string:
Book myBook = new Book("Title", "Author", 44);
string title = runMethod(myBook, "getTitle");
You can do this via Reflection.
Book myBook = new Book("Title", "Author", 44);
string title = (string) myBook.GetType().GetMethod("getTitle").Invoke(myBook, null);
You can use something like this, using reflection:
class Program
{
static void Main(string[] args)
{
var b = new Book("Book Title", 2342);
Console.WriteLine(CallMethod(b, "GetTitle", "Not Found"));
}
public static K CallMethod<T,K>(T a, string method, K defaultOjb)
{
var t = a.GetType();
var mi = t.GetMethod(method);
if (mi == null) return defaultOjb;
var ret=mi.Invoke(a, new object[] {});
return (K) ret;
}
}
public class Book
{
private readonly string _title;
private readonly decimal _price;
public decimal GetPrice()
{
return _price;
}
public string GetTitle()
{
return _title;
}
public Book(string title, decimal price)
{
_title = title;
_price = price;
}
}
Lookup reflection and MethodInfo. I believe that will lead you down the path you are looking for.
Previous answers are correct in mentioning reflection.
However, unless your true question is very different from your example it's unnecessary.
Judging from your example you could simply call it directly:
string title = mybook.getTitle();
If the point is that you don't know and don't want to care what specific object you're being given you can either use a base class, or an interface.
public interface IProduct
{
string Name { get; }
string Type { get; }
float Price { get; }
}
Make your classes implement IProduct and you're guaranteed that your classes will have implemented the properties or functions you've required, and that they will be public no matter whether you're dealing with "Book", "Apple", or "Door".
public void OutputProductsToConsole(List<IProduct> products)
{
for (int i = 0; i < products.Count; i++)
{
Console.WriteLine(products[i].Name + ": " + products[i].Price);
}
}
It is possible with reflection, but in the example, it would be simpler to just call the method directly:
string title = myBook.getTitle();
You are instantiating your new Book class with the property values. Are you not assigning the values so you can get them back later?
public class Book
{
private string _title;
private decimal _price;
private string _author;
public Book(string title, decimal price, string author);
{
_title = title;
_price = price;
_author = author;
}
public string Title
{
get
{
return _title;
}
}
public decimal Price
{
get
{
return _price;
}
}
public string Author
{
get
{
return _author;
}
}
}
Better yet, if these methods are common to all your classes create an interface and inherit that in your classes.

LinFu - can't quite see how to do what I want

Just found LinFu - looks very impressive, but I can't quite see how to do what I want to do - which is multiple inheritance by mixin (composition/delegation as I'd say in my VB5/6 days - when I had a tool to generate the tedious repetitive delegation code - it was whilst looking for a C# equivalent that I found LinFu).
FURTHER EDIT: TO clarify what I mean by composition/delegation and mixin.
public class Person : NEOtherBase, IName, IAge
{
public Person()
{
}
public Person(string name, int age)
{
Name = name;
Age = age;
}
//Name "Mixin" - you'd need this code in any object that wanted to
//use the NameObject to implement IName
private NameObject _nameObj = new NameObject();
public string Name
{
get { return _nameObj.Name; }
set { _nameObj.Name = value; }
}
//--------------------
//Age "Mixin" you'd need this code in any object that wanted to
//use the AgeObject to implement IAge
private AgeObject _ageObj = new AgeObject();
public int Age
{
get { return _ageObj.Age; }
set { _ageObj.Age = value; }
}
//------------------
}
public interface IName
{
string Name { get; set; }
}
public class NameObject : IName
{
public NameObject()
{}
public NameObject(string name)
{
_name = name;
}
private string _name;
public string Name { get { return _name; } set { _name = value; } }
}
public interface IAge
{
int Age { get; set; }
}
public class AgeObject : IAge
{
public AgeObject()
{}
public AgeObject(int age)
{
_age = age;
}
private int _age;
public int Age { get { return _age; } set { _age = value; } }
}
Imagine objects with many more properties, used in many more "subclasses" and you start to see the tedium. A code-gernation tool would actually be just fine...
So, LinFu....
The mixin example below is fine but I'd want to have an actual Person class (as above) - what's the LinFu-esque way of doing that? Or have I missed the whole point?
EDIT: I need to be able to do this with classes that are already subclassed.
DynamicObject dynamic = new DynamicObject();
IPerson person = null;
// This will return false
bool isPerson = dynamic.LooksLike<IPerson>();
// Implement IPerson
dynamic.MixWith(new HasAge(18));
dynamic.MixWith(new Nameable("Me"));
// Now that it’s implemented, this
// will be true
isPerson = dynamic.LooksLike<IPerson>();
if (isPerson)
person = dynamic.CreateDuck<IPerson>();
// This will return “Me”
string name = person.Name;
// This will return ‘18’
int age = person.Age;

In C#, how to instantiate a passed generic type inside a method?

How can I instantiate the type T inside my InstantiateType<T> method below?
I'm getting the error: 'T' is a 'type parameter' but is used like a 'variable'.:
(SCROLL DOWN FOR REFACTORED ANSWER)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TestGeneric33
{
class Program
{
static void Main(string[] args)
{
Container container = new Container();
Console.WriteLine(container.InstantiateType<Customer>("Jim", "Smith"));
Console.WriteLine(container.InstantiateType<Employee>("Joe", "Thompson"));
Console.ReadLine();
}
}
public class Container
{
public T InstantiateType<T>(string firstName, string lastName) where T : IPerson
{
T obj = T();
obj.FirstName(firstName);
obj.LastName(lastName);
return obj;
}
}
public interface IPerson
{
string FirstName { get; set; }
string LastName { get; set; }
}
public class Customer : IPerson
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Company { get; set; }
}
public class Employee : IPerson
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int EmployeeNumber { get; set; }
}
}
REFACTORED ANSWER:
Thanks for all the comments, they got me on the right track, this is what I wanted to do:
using System;
namespace TestGeneric33
{
class Program
{
static void Main(string[] args)
{
Container container = new Container();
Customer customer1 = container.InstantiateType<Customer>("Jim", "Smith");
Employee employee1 = container.InstantiateType<Employee>("Joe", "Thompson");
Console.WriteLine(PersonDisplayer.SimpleDisplay(customer1));
Console.WriteLine(PersonDisplayer.SimpleDisplay(employee1));
Console.ReadLine();
}
}
public class Container
{
public T InstantiateType<T>(string firstName, string lastName) where T : IPerson, new()
{
T obj = new T();
obj.FirstName = firstName;
obj.LastName = lastName;
return obj;
}
}
public interface IPerson
{
string FirstName { get; set; }
string LastName { get; set; }
}
public class PersonDisplayer
{
private IPerson _person;
public PersonDisplayer(IPerson person)
{
_person = person;
}
public string SimpleDisplay()
{
return String.Format("{1}, {0}", _person.FirstName, _person.LastName);
}
public static string SimpleDisplay(IPerson person)
{
PersonDisplayer personDisplayer = new PersonDisplayer(person);
return personDisplayer.SimpleDisplay();
}
}
public class Customer : IPerson
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Company { get; set; }
}
public class Employee : IPerson
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int EmployeeNumber { get; set; }
}
}
Declare your method like this:
public string InstantiateType<T>(string firstName, string lastName)
where T : IPerson, new()
Notice the additional constraint at the end. Then create a new instance in the method body:
T obj = new T();
Couple of ways.
Without specifying the type must have a constructor:
T obj = default(T); //which will produce null for reference types
With a constructor:
T obj = new T();
But this requires the clause:
where T : new()
To extend on the answers above, adding where T:new() constraint to a generic method will require T to have a public, parameterless constructor.
If you want to avoid that - and in a factory pattern you sometimes force the others to go through your factory method and not directly through the constructor - then the alternative is to use reflection (Activator.CreateInstance...) and keep the default constructor private. But this comes with a performance penalty, of course.
you want new T(), but you'll also need to add , new() to the where spec for the factory method
A bit old but for others looking for a solution, perhaps this could be of interest: http://daniel.wertheim.se/2011/12/29/c-generic-factory-with-support-for-private-constructors/
Two solutions. One using Activator and one using Compiled Lambdas.
//Person has private ctor
var person = Factory<Person>.Create(p => p.Name = "Daniel");
public static class Factory<T> where T : class
{
private static readonly Func<T> FactoryFn;
static Factory()
{
//FactoryFn = CreateUsingActivator();
FactoryFn = CreateUsingLambdas();
}
private static Func<T> CreateUsingActivator()
{
var type = typeof(T);
Func<T> f = () => Activator.CreateInstance(type, true) as T;
return f;
}
private static Func<T> CreateUsingLambdas()
{
var type = typeof(T);
var ctor = type.GetConstructor(
BindingFlags.Instance | BindingFlags.CreateInstance |
BindingFlags.NonPublic,
null, new Type[] { }, null);
var ctorExpression = Expression.New(ctor);
return Expression.Lambda<Func<T>>(ctorExpression).Compile();
}
public static T Create(Action<T> init)
{
var instance = FactoryFn();
init(instance);
return instance;
}
}
You can also use reflection to fetch the object's constructor and instantiate that way:
var c = typeof(T).GetConstructor();
T t = (T)c.Invoke();
Using a factory class to build your object with compiled lamba expression: The fastest way I've found to instantiate generic type.
public static class FactoryContructor<T>
{
private static readonly Func<T> New =
Expression.Lambda<Func<T>>(Expression.New(typeof (T))).Compile();
public static T Create()
{
return New();
}
}
Here is the steps I followed to set up the benchmark.
Create my benchmark test method:
static void Benchmark(Action action, int iterationCount, string text)
{
GC.Collect();
var sw = new Stopwatch();
action(); // Execute once before
sw.Start();
for (var i = 0; i <= iterationCount; i++)
{
action();
}
sw.Stop();
System.Console.WriteLine(text + ", Elapsed: {0}ms", sw.ElapsedMilliseconds);
}
I've also tried using a factory method:
public static T FactoryMethod<T>() where T : new()
{
return new T();
}
For the tests I've created the simplest class :
public class A { }
The script to test:
const int iterations = 1000000;
Benchmark(() => new A(), iterations, "new A()");
Benchmark(() => FactoryMethod<A>(), iterations, "FactoryMethod<A>()");
Benchmark(() => FactoryClass<A>.Create(), iterations, "FactoryClass<A>.Create()");
Benchmark(() => Activator.CreateInstance<A>(), iterations, "Activator.CreateInstance<A>()");
Benchmark(() => Activator.CreateInstance(typeof (A)), iterations, "Activator.CreateInstance(typeof (A))");
Results over 1 000 000 iterations:
new A(): 11ms
FactoryMethod A(): 275ms
FactoryClass A .Create(): 56ms
Activator.CreateInstance A (): 235ms
Activator.CreateInstance(typeof (A)): 157ms
Remarks: I've tested using both .NET Framework 4.5 and 4.6 (equivalent results).
Instead of creating a function to Instantiate the type
public T InstantiateType<T>(string firstName, string lastName) where T : IPerson, new()
{
T obj = new T();
obj.FirstName = firstName;
obj.LastName = lastName;
return obj;
}
you could have done it like this
T obj = new T { FirstName = firstName, LastName = lastname };

Categories