I have a method that gets an object that can be of various types. Depending of the type of the object I need to do different actions. My current code is like this:
public void SomeMethod(object obj)
{
int? someId = null;
Class1 class1 = obj as Class1;
Class2 class2 = obj as Class2;
Class3 class3 = obj as Class3;
Class4 class4 = obj as Class4;
if (class1 != null && class1.SomeProperty != null)
{
someId = class1.SomeProperty.Id;
}
else if (class2 != null && class2.AnotherProperty != null)
{
someId = class2.AnotherProperty.AnotherId;
}
...
AnotherMethod(someId);
}
I am not quite satisfied with this code as I do have some unnecessary casts. Which would be the most efficient way to do such an operation? I was thinking about something like:
if (obj.GetType().Equals(typeOf(Class1))
{
someId = ((Class1)obj).SomeProperty.Id;
}
Any suggestions?
Both alternatives are pretty bad, because they do explicit casts, and dispatch by checking the type manually. This is error-prone, and leads to inevitable maintenance headaches when you expand the list of types that your method needs to handle.
Starting with .NET 4.0, you have a better option - dispatch using dynamic:
public void SomeMethod(dynamic obj) {
SomeMethodImpl(obj);
}
private void SomeMethodImpl(Class1 obj) {
// Perform actions specific to Class 1
}
private void SomeMethodImpl(Class2 obj) {
// Perform actions specific to Class 2
}
private void SomeMethodImpl(Class3 obj) {
// Perform actions specific to Class 3
}
private void SomeMethodImpl(Class4 obj) {
// Perform actions specific to Class 4
}
private void SomeMethodImpl(object obj) {
// Catch all
}
Now you can place the code specific to a class in its own overload of SomeMethodImpl, without running a chain of conditional statements. Expanding your method to handle additional types is simple as well - all you need to do is adding another overload.
Note: I assume that the signature of SomeMethod must remain the same - in other words, you cannot address this problem simply by overloading SomeMethod.
Polymorphism??
public void SomeMethod(Class1 class1)
{
AnotherMethod(class1.SomeProperty.Id);
}
public void SomeMethod(Class2 class2)
{
AnotherMethod(class2.NewProperty.Id);
}
.
.
.
Instead why not call AnotherMethod(class1.SomeProperty.Id);,.. AnotherMethod(class2.NewProperty.Id) directly if that is all you wanted to do...
If you really want to check if the object is of certain type use if(obj is Class1) instead of casting it
I think you should first try doing this without casting. You can define an interface and explicitly implement this interface for each Classn. I assume Classn classes are not third party and you can modify them.
public interface IIdProvider {
int? Id { get; }
}
public class Class1 : IIdProvider {
int? IIdProvider.Id {
get {
return SomeProperty != null ? SomeProperty.Id : null;
}
}
}
public class Class2 : IIdProvider {
int? IIdProvider.Id {
get {
return AnotherProperty != null ? AnotherProperty.AnotherId : null;
}
}
}
Having this, SomeMethod does not care where the Id comes from. If you want to add Class5, Class6 etc you do not have to modify SomeMethod. Instead each newly added class will take care of the Id thing itself. Having this, we can do the following.
public void SomeMethod(IIdProvider obj)
{
AnotherMethod(obj.Id);
}
In this particular case (get single value of a variable), it could be more efficient to use switch-like approach, something like:
public int? GetSomeId(object obj) {
Class1 class1 = obj as Class1;
if (class1 != null)
{
return class1.SomeProperty != null ? class1.SomeProperty.Id : (int?)null;
}
Class2 class2 = obj as Class2;
if (class2 != null)
{
return class2.AnotherProperty != null ? class2.AnotherProperty.AnotherId : (int?)null;
}
....
return null;
}
as keyword exists for programmer conciseness. It gets translated to
Class1 class1 = obj is Class1 ? (Class1)obj : null;
I thinks go with as as it looks more readable and also does not affect performance.
I would use:
if (obj is Class1 && ((Class1)obj).SomeProperty)
someId = ((Class1)obj).SomeProperty.Id;
Final code would look like this:
if (obj is Class1 && ((Class1)obj).SomeProperty)
someId = ((Class1)obj).SomeProperty.Id;
else if (obj is Class2 && ((Class2)obj).AnotherProperty)
someId = ((Class2)obj).AnotherProperty.Id;
else if (obj is Class3 && ((Class3)obj).OnceAgainAnotherProperty)
...
In every if and else if conditions, if the first check obj is X fails it will not do the second ((X)obj).XProperty. So at the end of the day, only two casts will be performed, even if your object as the type Class4.
Related
I suppose method call chain below.
void DoSomething()
{
ObjectA a = CreateA();
if (a != null)
{
a.Foo();
}
}
ObjectA CreateA()
{
ObjectB b = CreateB();
if (b != null)
{
ObjectA a = b.ToA();
return a;
}
return null;
}
If method call depth get deeper, null checking will be more overlapped.
Is there any good solution for this?
Modified
I changed example code. It can't solve my problem that change CreateA to constructor.
The problem is only unnecessary null check chaining overlapping.
void SetImage()
{
UISprite image = GetSprite();
if (image != null)
{
image.spriteName = "hat";
}
}
UISprite GetSprite()
{
UISprite image = GetComponent<UISprite>();
if (image != null)
{
image.width = 100;
image.height = 100;
return image;
}
return null;
}
Starting with C# 6.0 you can use Null-Conditional Operator, which lets you make null-checking implicitly:
var result = possiblyNull?.MethodThatCanReturnNull()?.SomeProperty;
This construct will produce a null result if any element in the chain produces null.
You can do
void DoSomething()
{
CreateA()?.Foo();
}
ObjectA CreateA()
{
return CreateB()?.ToA();
}
Your other approach if you can't use C# 6, is don't return nulls, use null objects that way you never have to deal with null checking ( but you can still check if something is the null object )
If you are using C# 6.0 or higher, you got an easy solution with Null conditional operators for this issue.
see this link
https://msdn.microsoft.com/en-au/library/dn986595.aspx?f=255&MSPPError=-2147217396&cs-save-lang=1&cs-lang=csharp#code-snippet-1
So, assuming you (or someone else) can't use the null-conditional operator, is there a good reason to be using this pattern of methods creating objects instead of constructors creating the objects? Constructors are guaranteed not to return null.
It looks like you have some conversion or nested object heirarchy, but no inheritance heirarchy where you could just fall back on polymorphism. Maybe a tool like AutoMapper could be useful to encode these ToX() methods in a consistent manner?
I'm not sure how "nested" this would be. Your CreateB() method is going to look exactly like your CreateA() code. You're not going to end up with a "pyramid," just a lot of identical methods.
ObjectB CreateB()
{
ObjectC c = CreateC();
if (c != null)
{
ObjectB b = c.ToB();
return b;
}
return null;
}
Most of the time, you're doing this in an environment where you don't control all the classes. In that case, writing your own conversion functions or AutoMapper (really, worth the time) is the best approach. But, if you own the class hierarchy you might implement an abstract class that will do most of the heavy lifting for you. But honestly, I would only write something like this if I had a really good reason (something more than I just wanted to fuck with people). I include this to demonstrate how much simpler life is if you just use a constructor, which is guaranteed not to return null;
public abstract class MyAbstractObject<Tobj> where TObj: MyAbstractObject, new()
{
public static MyAbstractObject CreateObject()
{
Tobj subOb = new TObj();
MyAbstractObject parent = subOb.ToObject();
return parent;
}
public virtual TObj ToObject()
{
return CreateObject();
}
}
public class ObjectD : MyAbstractObject<ObjectC> { }
public class ObjectC : MyAbstractObject<ObjectB> { }
public class ObjectB : MyAbstractObject<ObjectA> { }
public class ObjectA : MyAbstractObject<ObjectA>
{
public override TObj ToObject()
{
return this;
}
}
static void Main()
{
ObjectA a = ObjectD.CreateObject();
}
I have a homework and I have to compare 2 object's by one of their properties, but since I'm working with generic types on my linked list where I have to store the objects I can't really reach the object's certain property (I'm using an interface, and all of the classes implement that interface)
So I have got a major interface, and some classes (i.e. class1, class2) that inherit the interface properties such as Age, or any kind of number that is comparable easily. In Main() I just created a new LinkedList and created some class1, class2 objects. I put them in the ordered list with that SortedListAddElement method, but I'm stuck at the part where it should compare the element's by the int properties. How should I go on from there with this source code? Should I change the first line to: class List : IEnumerable, IComparable, IMajorInterface? Or change something in CompareTo()? Please help!
interface IMajorInterface
{
string Name{ get; }
int Age { get; set; }
}
class List<T> : IEnumerable<T>, IComparable<T>
{
ListElement<T> head;
public List()
{
head = null;
}
public void SortedListAddElement(T newValue)
{
ListElement<T> new = new ListElement<T>(newValue);
ListElement<T> p = head;
ListElement<T> e = null;
while (p != null /* && this is the part where I should compare the p and new objects by their property, for example the Age property, like: p.Age < new.Age */)
{
e = p;
p = p.Next;
}
if (e == null)
{
new.Next = head;
head = new;
}
else
{
new.Next = p;
e.Next = new;
}
}
public int CompareTo(T obj)
{
if (obj == null)
{
return -1;
}
else
{
if (obj is T)
{
T obj2 = obj as T;
return obj.Age.CompareTo(obj2.Age);
}
else
{
return -1;
}
}
}
There are several options to solve that. Here is one approach. First, make your major interface comparable:
interface IMajorInterface : IComparable<IMajorInterface>
{
string Name{ get; }
int Age { get; set; }
}
Then constrain your generic type parameter in the list class implementation:
class List<T> : IEnumerable<T>
where T : IComparable<T>
{
// ... Code omitted for brevity.
}
Then implement the IComparable interface in your concrete major classes (class1, class2). Maybe it would be advisable to implement a base class for those, implement the interface there and derive the class1 and class2, etc. from that base class. Perhaps it would be even better to drop the IMajorInterface altogether and just make an abstract Major base class.
Alternatively, as you are only using the list for majors, you could just constrain the generic list parameter to the IMajorInterface or Major base class itself. That would be the simplest (and least flexible) solution:
class List<T> : IEnumerable<T>
where T : IMajorInterface // No need to implement IComparable<T> in any class.
{
// ... Code omitted for brevity.
}
Finally, as another approach, you could provide an IComparer<T> to the list on its constructor, just as the System.Collections.Generic classes do. Investigate on MSDN.
I hope it helps. Happy coding!
you can implement IComparer.
class ageComparer : IComparer<Person>
{
public int Compare(Person x, Person y)
{
return x.Age - y.Age;
}
}
Have a look at this article http://www.blackwasp.co.uk/IComparer_2.aspx
Here's an article at c-sharpcorner that compares generic types:
http://www.c-sharpcorner.com/UploadFile/1a81c5/compare-2-objects-of-generic-class-type-in-C-Sharp/
Quick code snippet:
static bool Compare<T>(T Object1, T object2)
{
//Get the type of the object
Type type = typeof(T);
//return false if any of the object is false
if (Object1 == null || object2 == null)
return false;
//Loop through each properties inside class and get values for the property from both the objects and compare
foreach (System.Reflection.PropertyInfo property in type.GetProperties())
{
if (property.Name != "ExtensionData")
{
string Object1Value = string.Empty;
string Object2Value = string.Empty;
if (type.GetProperty(property.Name).GetValue(Object1, null) != null)
Object1Value = type.GetProperty(property.Name).GetValue(Object1, null).ToString();
if (type.GetProperty(property.Name).GetValue(object2, null) != null)
Object2Value = type.GetProperty(property.Name).GetValue(object2, null).ToString();
if (Object1Value.Trim() != Object2Value.Trim())
{
return false;
}
}
}
return true;
}
Can I get the type of a field? Type.GetType(); only returns the type of an instance, so if field is set null I cant get the Type.
Note: I would prefer not using reflections~
Depending on context GetProperty and PropertyType may work for you. I.e. if you have object type and property name:
var typeOfLength = typeof(String).GetProperty("Length").PropertyType;
It's not clear whether you only want the compile time type when the field is null. A simple method like this could work:
public static class ReflectionExtensions
{
public static Type GetCompileTimeType<T>(this T obj)
{
return typeof(T);
}
}
You could modify it it check for null and return the actual type if that is what you want.
usage:
class A { }
class B : A { }
class C
{
private A a1, a2;
public C()
{
a2 = new B();
Console.WriteLine(a1.GetCompileTimeType()); // null but prints A
Console.WriteLine(a2.GetCompileTimeType()); // actually a B but prints A
}
}
public class test
{
private int fTestInt;
private string fTestString;
}
You can achieve getting the field type by typing fTestInt.GetType().
If you want a quick type validation you can use.
if (fTestInt is int)
{
Console.Write("I'm an int!");
}
Not sure if this is what you're asking. Your question seems partial.
Why not just ask if is null ?
if (Type != null)
{
return Type.GetType().Name;
}
else
{
return "";
}
If I have:
void MyMethod(Object obj) { ... }
How can I cast obj to what its actual type is?
If you know the actual type, then just:
SomeType typed = (SomeType)obj;
typed.MyFunction();
If you don't know the actual type, then: not really, no. You would have to instead use one of:
reflection
implementing a well-known interface
dynamic
For example:
// reflection
obj.GetType().GetMethod("MyFunction").Invoke(obj, null);
// interface
IFoo foo = (IFoo)obj; // where SomeType : IFoo and IFoo declares MyFunction
foo.MyFunction();
// dynamic
dynamic d = obj;
d.MyFunction();
I don't think you can (not without reflection), you should provide a type to your function as well:
void MyMethod(Object obj, Type t)
{
var convertedObject = Convert.ChangeType(obj, t);
...
}
UPD:
This may work for you:
void MyMethod(Object obj)
{
if (obj is A)
{
A a = obj as A;
...
}
else if (obj is B)
{
B b = obj as B;
...
}
}
How about
JsonConvert.DeserializeObject<SomeType>(object.ToString());
You could use also Pattern Matching
void MyMethod(Object obj) {
if(obj is SomeType myVar){
myVar.MyFunction();
}
}
If your MyFunction() method is defined only in one class (and its descendants), try
void MyMethod(Object obj)
{
var o = obj as MyClass;
if (o != null)
o.MyFunction();
}
If you have a large number in unrelated classes defining the function you want to call, you should define an interface and make your classes define that interface:
interface IMyInterface
{
void MyFunction();
}
void MyMethod(Object obj)
{
var o = obj as IMyInterface;
if (o != null)
o.MyFunction();
}
In my case AutoMapper works well.
AutoMapper can map to/from dynamic objects without any explicit configuration:
public class Foo {
public int Bar { get; set; }
public int Baz { get; set; }
}
dynamic foo = new MyDynamicObject();
foo.Bar = 5;
foo.Baz = 6;
Mapper.Initialize(cfg => {});
var result = Mapper.Map<Foo>(foo);
result.Bar.ShouldEqual(5);
result.Baz.ShouldEqual(6);
dynamic foo2 = Mapper.Map<MyDynamicObject>(result);
foo2.Bar.ShouldEqual(5);
foo2.Baz.ShouldEqual(6);
Similarly you can map straight from dictionaries to objects, AutoMapper will line up the keys with property names.
more info https://github.com/AutoMapper/AutoMapper/wiki/Dynamic-and-ExpandoObject-Mapping
Cast it to its real type if you now the type for example it is oriented from class named abc.
You can call your function in this way :
(abc)(obj)).MyFunction();
if you don't know the function it can be done in a different way. Not easy always. But you can find it in some way by it's signature. If this is your case, you should let us know.
If multiple types are possible, the method itself does not know the type to cast, but the caller does, you might use something like this:
void TheObliviousHelperMethod<T>(object obj) {
(T)obj.ThatClassMethodYouWantedToInvoke();
}
// Meanwhile, where the method is called:
TheObliviousHelperMethod<ActualType>(obj);
Restrictions on the type could be added using the where keyword after the parentheses.
Another option is to serialise it and then deserialise it as the object you want.
JsonConvert.DeserializeObject<OtherType>(JsonConvert.SerializeObject(obj));
Implement an interface to call your function in your method
interface IMyInterface
{
void MyinterfaceMethod();
}
IMyInterface MyObj = obj as IMyInterface;
if ( MyObj != null)
{
MyMethod(IMyInterface MyObj );
}
Casting to actual type is easy:
void MyMethod(Object obj) {
ActualType actualyType = (ActualType)obj;
}
If I have a method with a parameter that's an interface, whats the fasts way to see if the interface's reference is of a specific generic type?
More specifically, if I have:
interface IVehicle{}
class Car<T> : IVehicle {}
CheckType(IVehicle param)
{
// How do I check that param is Car<int>?
}
I'm also going to have to cast after the check. So if there is a way to kill 2 birds with one stone on this one let me know.
To check if param is a Car<int> you can use "is" and "as" as normal:
CheckType(IVehicle param)
{
Car<int> car = param as Car<int>;
if (car != null)
{
...
}
}
Or, you can just do:
if(param is Car<int>)
{
// Hey, I'm a Car<int>!
}
Why not make this generic?
interface IVehicle{}
class Car<T> : IVehicle {
public static bool CheckType(IVehicle param)
{
return param is Car<T>;
}
}
...
Car<string> c1 = new Car<string>();
Car<int> c2 = new Car<int>();
Console.WriteLine(Car<int>.CheckType(c1));
Console.WriteLine(Car<int>.CheckType(c2));
The code differs quite dramatically depending on whether you want to know, if the reference is based on a generic type prototype, or a specialized one.
The specialized one is easy, you can just use is:
CheckType(IVehicle param)
{
var isofYourType = param is Car<int>;
...
}
or a safe cast, as shown before:
CheckType(IVehicle param)
{
var value = param as Car<int>;
if(value != null)
...
}
In case you wanted to know whether yur var is just some specialization of Car<T>, things get really ugly.
And the last you should thing to worry about is speed in this case, because that's gonna be even uglier than the code g:
class Car<T>
{ }
interface IVehicle { }
class YourCar : Car<int>, IVehicle
{ }
static bool IsOfType(IVehicle param)
{
Type typeRef = param.GetType();
while (typeRef != null)
{
if (typeRef.IsGenericType &&
typeRef.GetGenericTypeDefinition() == typeof(Car<>))
{
return true;
}
typeRef = typeRef.BaseType;
}
return false;
}
static void Main(string[] args)
{
IVehicle test = new YourCar();
bool x = IsOfType(test);
}
I often find that if my code requires me to write checks for specific types, I'm probably doing something wrong. You didn't give us enough context for us to give advice on this, though.
Does this meet your needs?
Car<int> carOfInt = param as Car<int>;
if (carOfInt != null)
{
// .. yes, it's a Car<int>
}
Use the "as" operator to do it all in one shot. "as" will return either an object of the type you want, or null if what you're checking against doesn't match. This will only work for reference types, though.
interface IVehicle { }
class Car<T> : IVehicle
{
static Car<int> CheckType(IVehicle v)
{
return v as Car<int>;
}
}
The "is" operator will let you test to see if v is an instance of Car<int>.