It's a training case. I have several classes with some similar properties - X and Y as coordinates for example. And I want to create a special class < T > with a function which have to change X and Y at the objects of this classes. I want to pass objects of this classes as < T > but the problem is that function doesn't know about X and Y at the object they accepted as a parameters.
namespace testing_Templates
{
internal class Program
{
static void Main(string[] args)
{
var temp = new Car();
var template = new TemplateTest<Car>();
Console.WriteLine(temp);
template.Move(temp, "Up", 20); // want to change Y of temp object of Car class
Console.WriteLine(temp);
}
// Special <T> class with function, changing X and Y in different class objects
class TemplateTest<T> where T: class
{
public int X { get; set; }
public int Y { get; set; }
public void Move(T obj, string direction, int steps)
{
TemplateTest<T> tempobj;
tempobj = (TemplateTest<T>) obj; //ERROR
Console.WriteLine(tempobj.Equals(obj));
switch (direction)
{
case "Up" :
{
this.Y = steps;
Console.WriteLine(tempobj.Equals(obj));
break;
}
case "Down":
{
this.Y -= steps;
break;
}
case "Left":
{
this.X -= steps;
break;
}
case "Right":
{
this.X = steps;
break;
}
default:
break;
}
}
}
// Test class with X and Y
class Car
{
int year;
string name;
int speed;
int x;
int y;
public Car()
{
year = 1974;
name = "Zhiguli";
speed = 60;
x = 20;
y = 0;
}
public Car(int year, string name, int speed)
{
this.year = year;
this.name = name;
this.speed = speed;
x = -20;
y = -10;
}
public int Year { get => year; set => year = value; }
public string Name { get => name; set => name = value; }
public int Speed { get => speed; set => speed = value; }
public int X { get => x; set => x = value; }
public int Y { get => y; set => y = value; }
public override string ToString()
{
return $"Car {Name} ({Year}) with speed {Speed} is on point {X},{Y}";
}
}
}
}
Is it possible to use class object as T in such tasks? If it's possible then what's wrong?
CodePudding user response:
In your case, you need to use interface
Create interface ITemplateObj
public interface ITemplateObj
{
public int X { get; set; }
public int Y { get; set; }
}
implement in type Car
class Car : ITemplateObj
then update the handler
class TemplateTest<T> where T : ITemplateObj
{
public void Move(T obj, string direction, int steps)
{
var tempobj = obj;
Console.WriteLine(tempobj.Equals(obj));
switch (direction)
{
case "Up":
{
obj.Y = steps;
Console.WriteLine(tempobj.Equals(obj));
break;
}
case "Down":
{
obj.Y -= steps;
break;
}
case "Left":
{
obj.X -= steps;
break;
}
case "Right":
{
obj.X = steps;
break;
}
default:
break;
}
}
}
full code like this:
void Main(string[] args)
{
var temp = new Car();
var template = new TemplateTest<Car>();
Console.WriteLine(temp);
template.Move(temp, "Up", 20); // want to change Y of temp object of Car class
Console.WriteLine(temp);
}
public interface ITemplateObj
{
public int X { get; set; }
public int Y { get; set; }
}
// Special <T> class with function, changing X and Y in diffirent class objects
class TemplateTest<T> where T : ITemplateObj
{
public void Move(T obj, string direction, int steps)
{
var tempobj = obj;
Console.WriteLine(tempobj.Equals(obj));
switch (direction)
{
case "Up":
{
obj.Y = steps;
Console.WriteLine(tempobj.Equals(obj));
break;
}
case "Down":
{
obj.Y -= steps;
break;
}
case "Left":
{
obj.X -= steps;
break;
}
case "Right":
{
obj.X = steps;
break;
}
default:
break;
}
}
}
// Test class with X and Y
class Car : ITemplateObj
{
int year;
string name;
int speed;
int x;
int y;
public Car()
{
year = 1974;
name = "Zhiguli";
speed = 60;
x = 20;
y = 0;
}
public Car(int year, string name, int speed)
{
this.year = year;
this.name = name;
this.speed = speed;
x = -20;
y = -10;
}
public int Year { get => year; set => year = value; }
public string Name { get => name; set => name = value; }
public int Speed { get => speed; set => speed = value; }
public int X { get => x; set => x = value; }
public int Y { get => y; set => y = value; }
public override string ToString()
{
return $"Car {Name} ({Year}) with speed {Speed} is on point {X},{Y}";
}
}
CodePudding user response:
Your example does not make all to much sense, but I suspect you want a generic constraint. This lets you use a generic object, as long as it fulfills some interface. For example:
public interface IPosition{
int X {get;set;}
int Y {get;set;}
}
class TemplateTest<T> where T: IPosition
public void Move(T obj, string direction, int steps){
// This works, since we have promised that all T
// have a X-property of type int
obj.X = steps;
}
}
However, in some cases generics is the wrong approach, and you should just replace the T
with your IPosition
. One possible advantage of generics is that it will compile multiple versions of the method, one for each T, and that may enable some optimizations. But this is only relevant in very specialized cases.