我想知道在C#中是否有一种基于基本类型的方法,并将其复制以使用其他基元。
我知道它不是很清楚,我真的不知道怎么解释这个(英语不是我的母语,对不起......)所以我会尝试用伪代码来解释它
一个简单的例子:
public struct Vector2d {
public double X;
public double Y;
//Arithmetic methods: Length, normalize, rotate, operators overloads, etc...
}
问题是我想要一个float和这种类型的int32版本。
我在做什么(有效的C#代码):
//This type contains all useful methods
public struct Vector2d {
public float X;
public float Y;
public Vector2f AsFloat() {
return new Vector2f((float)X, (float)Y);
}
public Vector2f AsInteger() {
return new Vector2i((int)X, (int)Y);
}
//Arithmetic methods
}
//These types are only here to be casted from/to, all the arithmetics methods are on the double-based type
public struct Vector2f {
public float X;
public float Y;
public Vector2f AsDouble() {
return new Vector2d(X, Y);
}
public Vector2f AsInteger() {
return new Vector2i((int)X, (int)Y);
}
}
public struct Vector2i {
public int X;
public int Y;
public Vector2f AsFloat() {
return new Vector2f(X, Y);
}
public Vector2f AsDouble() {
return new Vector2d(X, Y);
}
}
它有效,但不是“性感”,如果使用AsXXX方法广泛演员,将不可避免地对演出产生影响。
理想情况下,我会在所有三种类型上都使用算术方法,但维护它会很痛苦......
什么是理想的解决方案(伪代码,无效的C#):
public struct Vector2<T> where T : numeric {
public T X;
public T Y;
public T Length {
return (T)Math.Sqrt(X * X + Y * Y);
}
//Other arithmetic methods
}
我知道目前在C#中这是不可能的,但这是真正的问题:
您对如何妥善有效地处理此问题有任何想法吗?
我一直在想的(伪代码,无效的C#):
//The TYPE defined constant should be used by Vector2Body instead of plain typed "double", "float", etc...
public struct Vector2d {
#define TYPE double
#import Vector2Body
}
public struct Vector2f {
#define TYPE float
#import Vector2Body
}
public struct Vector2i {
#define TYPE int
#import Vector2Body
}
这样,我就不会有重复的代码,更容易维护
等待你的想法:)
PS:如果版主有关于如何更好地格式化我的问题的想法,请随时编辑它:)
答案 0 :(得分:5)
@ mike-z 使用T4模板给出了一个非常好的方法:
模板(.tt文件):
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
using System;
namespace My.Math {
<# Vector2Body("d", "double"); #>
<# Vector2Body("f", "float"); #>
<# Vector2Body("i", "int"); #>
}
<#+ private void Vector2Body(string suffix, string t) { #>
public struct Vector2<#= suffix #> {
public <#= t #> X;
public <#= t #> Y;
//Arithmetic for <#= t #>...
}
<#+ } #>
自动生成的代码:
using System;
namespace My.Math {
public struct Vector2d {
public double X;
public double Y;
//Arithmetic for double...
}
public struct Vector2f {
public float X;
public float Y;
//Arithmetic for float...
}
public struct Vector2i {
public int X;
public int Y;
//Arithmetic for int...
}
}
没有通用,因此没有性能影响,代码编写一次......
答案 1 :(得分:4)
你可以做点什么,
public struct Vector2<T> where T : IConvertible
{
private readonly double x;
private readonly double y;
public Vector2(T x, T y)
{
this.x = x.ToDouble(CultureInfo.CurrentCulture);
this.y = y.ToDouble(CultureInfo.CurrentCulture);
}
public T X
{
get
{
return ConvertBack(this.x);
}
}
public T Y
{
get
{
return ConvertBack(this.y);
}
}
private static T ConvertBack(double d)
{
return (t)Convert.ChangeType(d, typeof(T), CultureInfo.CurrentCulture);
}
}
但是,如果你不想要通用治疗。那么您可能还有几种专门的Vector2
类型。
答案 2 :(得分:0)
我想到了与Jodrell建议的解决方案相同的解决方案。 只想添加:
private Vector2(double x, double y)
{
this.x = x;
this.y = y;
}
public Vector2<E> ToVector<E>() where E : IConvertible
{
return new Vector2<E>(x, y);
}