How to Provide Custom Cast Support for My Class

How do I provide custom cast support for my class?

You would need to override the conversion operator, using either implicit or explicit depending on whether you want users to have to cast it or whether you want it to happen automagically. Generally, one direction will always work, that's where you use implicit, and the other direction can sometimes fail, that's where you use explicit.

The syntax is like this:

public static implicit operator dbInt64(Byte x)
{ return new dbInt64(x); }

or

public static explicit operator Int64(dbInt64 x)
{
if (!x.defined) throw new DataValueNullException();
return x.iVal;
}

For your example, say from your custom Type (MyType --> byte[] will always work):

public static implicit operator byte[] (MyType x)
{
byte[] ba = // put code here to convert x into a byte[]
return ba;
}

or

public static explicit operator MyType(byte[] x)
{
if (!CanConvert) throw new DataValueNullException();

// Factory to convert byte[] x into MyType
return MyType.Factory(x);
}

How do I provide custom cast between two classes with Type arguments in C#

Your problem is that you are not creating the correct view model.

public ActionResult Create(int id)
{
AnimalType t = DbContext.AnimalTypes.Find(id); // get AnimalType object from database
AnimalViewModel<Animal> model = new AnimalViewModel<Animal>()
{
Animal = (Animal)t.CreateInstance() // Returns a Tiger object cast to an Animal
};

return View(model);
}

What you need to do is get a handle on the correct ViewModel type and create an instance of that with the correct generic. An Animal will always be an Animal no matter if you set it to a tiger or anything else unless you cast it to what it is supposed to be or attempt to call everything dynamically.

The code below will actually create you an AnimalViewModel<Tiger> instead of AnimalViewModel<Animal> which is causing your issues.

public class AnimalViewModel<T> where T : Animal
{
public T Animal { get; set; }

public AnimalViewModel(T animal)
{
Animal = animal;
}
}
public ActionResult Create(int id)
{
AnimalType t = DbContext.AnimalTypes.Find(id); // get AnimalType object from database
Animal animal = (Animal)t.CreateInstance();
var animalViewModel =
Activator.CreateInstance(typeof(AnimalViewModel<>).MakeGenericType(animal.GetType()),
animal)

return View(animalViewModel);
}

How to write custom casting method in Java

You can't overload the cast operator. Java doesn't support it and probably never will.

To convert a single value to an instance of the desired class, we use static factory methods.

public static Person fromAge(int age) {
return new Person(age);
}

They often return a partially constructed object. In the snippet above, a newly constructed person has only age set: other fields will have their default values.

To do the opposite, we use getters.

public int getAge() {
return age;
}

However, since toString is already there, it makes sense to add other data types as well.

toInt makes no sense when it's applied to me (as an instance of the Person class). It could be my height, my weight, my age, a number of times I went to a bathroom today, etc. I can't represent myself by one int number, neither can a large majority of classes.

On the other hand, toString can do this job pretty well: I can give you (read return) a summary of my hobbies, my biometric information, even my picture. Or I can leave it to the default implementation, which still would satisfactorily represent an object.

How to make type cast for python custom class

As noted by Anand in comments, what you're looking for is object serialization and deserialization. One way to achieve this is through the pickle (or cPickle) module:

>>> import pickle

>>> class Example():
... def __init__(self, x):
... self.x = x
...
>>> a = Example('foo')
>>> astr = pickle.dumps(a) # (i__main__\nExample\np0\n(dp1\nS'x'\np2\nS'foo'\np3\nsb.
>>> b = pickle.loads(astr)
>>> b
<__main__.Example instance at 0x101c89ea8>
>>> b.x
'foo'

Note, however, that one gotcha in using the pickle module is dealing with implementation versions. As suggested in the Python docs, if you want an unpickled instance to automatically handle implementation versioning, you may want to add a version instance attribute and add a custom __setstate__ implementation: https://docs.python.org/2/library/pickle.html#object.setstate. Otherwise, the version of the object at serialization time will be exactly what you get at deserialization time, regardless of code changes made to the object itself.

Allow casting a string to my Class

It sounds like your user variable is of type object. You've only provided conversion support for the following scenarios:

  • stringSystemUser
  • SystemUserstring

While your user variable might contain a reference to an instance of string, it can't be implicitly downcast to string.

string (or any other type, for that matter) can be implicitly upcast to object (since string is object evaluates to true), the converse is not possible. An object instance can't be implicitly downcast to string since object is string evaluates to false.

You can:

  • explicitly cast your object to string and then to SystemUser, or

    object     user     = GetStringRepresentingUser() ;
    SystemUser instance = (SystemUser)(string)user ;
  • change the data type of user to string

    string     user     = GetStringRepresentingUser() ;
    SystemUser instance = (SystemUser)user ;

Edited to Note:

Adding overloads may help you here. You can do something like this:

public static SystemUser GetSystemUser( object o )
{
SystemUser instance ;
if ( o is string )
{
instance = GetSystemUser( (string) o ) ;
}
else
{
instance = (SystemUser) o ;
}
return instance ;
}
public static SystemUser GetSystemUser( string s )
{
return (SystemUser) s ;
}

You might also consider using the Parse()`TryParse()` idiom:

public static SystemUser Parse( string s )
{
// parse the string and construct a SystemUser instance
// throw a suitable exception if the parse is unsuccessful
}
public static bool TryParse( string s , out SystemUser instance )
{
// as above, except no exception is thrown on error.
// instead, return true or false, setting instance to default(SystemUser) (null)
// if the conversion wasnt' possible.
}

Using Parse()/TryParse() is likely to get more easily understood as well.

Not matter how you do it, at some point you're going to have to look at your object and check its type:

  • If its actually a string, excplicity downcast to string and deserialize (parse) it back into an instance of your class, or...

  • If it's not a string, it must be an instance of your type: excplicity downcast it.

How to custom cast a list to a different type?

I managed to solve the problem by also implementing a conversion in the 'StudentView' class from 'StudentView' to 'Student' and then using Magnetron's solution.

So I implemented a conversion in the 'View' class. Why this is needed I have no idea, seems magical to me considering this conversion shouldn't be necessary for the conversion of 'Student' to 'StudentView'. Perhaps there is something written somewhere that a two way cast is required for some reason.

public class StudentView : ViewBase<Student>
{
// Removed for brevity

public static implicit operator Student(StudentView student)
{
return new Student(student);
}

}

Then updated the casting to be performed like so as highlighted by Magnetron:

    public async Task OnGetAsync()
{
Student = await _context.Student.Select(x => (StudentView)x).ToListAsync();
}

I'd also like to highlight billybob's answer as he provided another correct way to solve the solution, I just chose a different way.

C#: Custom casting to a value type

You will have to overload the cast operator.

    public class Foo
{
public Foo( double d )
{
this.X = d;
}

public double X
{
get;
private set;
}

public static implicit operator Foo( double d )
{
return new Foo (d);
}

public static explicit operator double( Foo f )
{
return f.X;
}

}


Related Topics



Leave a reply



Submit