@SergeySerge11

Как сделать шаблонный метод для мат операций с числами и Типом Vector2?

static T fun<T>(T a,T b) where T : unmanaged///,INumber<T>, IAdditionOperators<T,T,T> ????
     {
         return a + b;
     }
     fun<Vector2>(v1,v2);
     fun(1,2);

У типов есть перегрузки методов +-*/ но у Vector2 нету вообще ни каких интерфейсов,

Без оберток и двойной диспетчеризации(если только они не замедляют доступ).
В принципе я уже как-то делал, через когенерацию, но много мороки
Типа может есть какой-то способ из коробки, или в net 8.0 появится.
  • Вопрос задан
  • 54 просмотра
Пригласить эксперта
Ответы на вопрос 2
AshBlade
@AshBlade Куратор тега C#
Просто хочу быть счастливым
Интерфейсов чисел он не реализует. Есть 2 костыля:
1. Вести словарь функций сложения
var typeToFunc = new Dictionary<Type, AddFunc>() {{typeof(int), IntAdd}, {typeof(Vector2), Vector2Add}};

var left = 123;
var right = 14455;
var result = Add(left, right);
Console.WriteLine($"Результат сложения {left} и {right} = {result}");

var leftVector = new Vector2(123, 55);
var rightVector = new Vector2(55, 111);
var resultVector = Add(leftVector, rightVector);
Console.WriteLine($"Результат сложения {leftVector} и {rightVector} = {resultVector}");

T Add<T>(T left, T right)
{
    return ( T ) typeToFunc[typeof(T)](left, right);
}

object Vector2Add(object left, object right)
{
    return ( Vector2 ) left + ( Vector2 ) right;
}

object IntAdd(object left, object right)
{
    return (int) left + (int) right;
}

delegate object AddFunc(object left, object right);

2. Создай монаду с int и Vector2
var number = NumberOrVector2<int>.FromNumber(123);
var newNumber = number.Add(() => 23, () => throw new InvalidOperationException("хранится число"));
if (newNumber.TryGetNumber(out var result))
{
    Console.WriteLine($"Получился результат: {result}");
}
else
{
    Console.WriteLine($"Ошибка - хранился вектор");
}

public readonly struct NumberOrVector2<TNumber> where TNumber: unmanaged, INumber<TNumber>
{
    private readonly TNumber _number;
    private readonly Vector2? _vector;

    private NumberOrVector2(TNumber number, Vector2? vector)
    {
        _number = number;
        _vector = vector;
    }

    public bool TryGetNumber(out TNumber number)
    {
        number = _number;
        return !_vector.HasValue;
    }

    public bool TryGetVector(out Vector2 vector)
    {
        vector = _vector.GetValueOrDefault();
        return _vector.HasValue;
    }

    public NumberOrVector2<TNumber> Add(Func<TNumber> numberAdd, Func<Vector2> vectorAdd)
    {
        if (_vector is {} vector)
        {
            return new NumberOrVector2<TNumber>(_number, vector + vectorAdd());
        }

        return new NumberOrVector2<TNumber>(_number + numberAdd(), null);
    }
    
    public static NumberOrVector2<TNumber> FromNumber(TNumber number)
    {
        return new NumberOrVector2<TNumber>(number, null);
    }
    
    public static NumberOrVector2<TNumber> FromVector(Vector2 vector)
    {
        return new NumberOrVector2<TNumber>(default, vector);
    }
}
Ответ написан
Комментировать
vabka
@vabka Куратор тега C#
Токсичный шарпист
Vector2 не реализует интерфейсы INumber и прочие новые => никак ты вокруг него женерик не сделаешь.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы