Pertanyaan Solusi untuk kendala operator yang berlebihan dalam .NET generics


Apa yang akan saya lakukan jika saya ingin memiliki metode generik yang hanya menerima jenis yang telah membebani operator, misalnya operator pengurangan. Saya mencoba menggunakan antarmuka sebagai kendala tetapi antarmuka tidak dapat memiliki operator yang terlalu banyak.

Apa cara terbaik untuk mencapai ini?


32
2017-09-29 05:37


asal


Jawaban:


Tidak ada jawaban segera; operator bersifat statis, dan tidak dapat diekspresikan dalam batasan - dan primata yang ada tidak mengimplementasikan antarmuka tertentu (berbeda dengan IComparable [<T>] yang dapat digunakan untuk mengemulasi lebih besar dari / kurang dari).

Namun; jika Anda hanya ingin bekerja, maka dalam. NET 3.5 ada beberapa opsi ...

Saya telah mengumpulkan sebuah perpustakaan sini yang memungkinkan akses yang efisien dan sederhana ke operator dengan obat generik - seperti:

T result = Operator.Add(first, second); // implicit <T>; here

Ini dapat diunduh sebagai bagian dari MiscUtil

Selain itu, dalam C # 4.0, ini menjadi mungkin melalui dynamic:

static T Add<T>(T x, T y) {
    dynamic dx = x, dy = y;
    return dx + dy;
}

Saya juga punya (pada satu titik) versi .NET 2.0, tetapi itu kurang teruji. Pilihan lainnya adalah membuat antarmuka seperti

interface ICalc<T>
{
    T Add(T,T)() 
    T Subtract(T,T)()
} 

dll, tetapi kemudian Anda harus lulus ICalc<T>; melalui semua metode, yang menjadi berantakan.


41
2017-09-29 05:46



Saya menemukan bahwa IL benar-benar dapat menangani hal ini dengan cukup baik. Ex.

ldarg.0
ldarg.1
add
ret

Dikompilasi dalam metode generik, kode akan berjalan baik selama tipe primitif ditentukan. Dimungkinkan untuk memperpanjang ini untuk memanggil fungsi operator pada jenis non-primitif.

Lihat sini.


7
2018-06-26 00:00



Ada sepotong kode yang dicuri dari internats yang saya gunakan banyak untuk ini. Ini terlihat atau dibangun menggunakan IL operator aritmatika dasar. Itu semua dilakukan dalam suatu Operation<T> kelas generik, dan yang harus Anda lakukan adalah menetapkan operasi yang diperlukan ke dalam delegasi. Seperti add = Operation<double>.Add.

Ini digunakan seperti ini:

public struct MyPoint
{
    public readonly double x, y;
    public MyPoint(double x, double y) { this.x=x; this.y=y; }
    // User types must have defined operators
    public static MyPoint operator+(MyPoint a, MyPoint b)
    {
        return new MyPoint(a.x+b.x, a.y+b.y);
    }
}
class Program
{
    // Sample generic method using Operation<T>
    public static T DoubleIt<T>(T a)
    {
        Func<T, T, T> add=Operation<T>.Add;
        return add(a, a);
    }

    // Example of using generic math
    static void Main(string[] args)
    {
        var x=DoubleIt(1);              //add integers, x=2
        var y=DoubleIt(Math.PI);        //add doubles, y=6.2831853071795862
        MyPoint P=new MyPoint(x, y);
        var Q=DoubleIt(P);              //add user types, Q=(4.0,12.566370614359172)

        var s=DoubleIt("ABC");          //concatenate strings, s="ABCABC"
    }
}

Operation<T> Sisipan kode sumber dari bin tempel: http://pastebin.com/nuqdeY8z

dengan atribusi di bawah ini:

/* Copyright (C) 2007  The Trustees of Indiana University
 *
 * Use, modification and distribution is subject to the Boost Software
 * License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
 * http://www.boost.org/LICENSE_1_0.txt)
 *  
 * Authors: Douglas Gregor
 *          Andrew Lumsdaine
 *          
 * Url:     http://www.osl.iu.edu/research/mpi.net/svn/
 *
 * This file provides the "Operations" class, which contains common
 * reduction operations such as addition and multiplication for any
 * type.
 *
 * This code was heavily influenced by Keith Farmer's
 *   Operator Overloading with Generics
 * at http://www.codeproject.com/csharp/genericoperators.asp
 *
 * All MPI related code removed by ja72. 
 */

-1
2017-08-18 14:09