أين يمكنني العثور على وظيفة "المشبك" في .NET؟

StackOverflow https://stackoverflow.com/questions/2683442

  •  30-09-2019
  •  | 
  •  

سؤال

أرغب في الحصول على قيمة x إلى نطاق [a, b]:

x = (x < a) ? a : ((x > b) ? b : x);

هذا أساسي تمامًا. لكنني لا أرى وظيفة "مشبك" في مكتبة الفصل - على الأقل ليس في System.Math.

(لكي لا يعلم "المشبك" القيمة ، التأكد من أنها تقع بين بعض القيم القصوى والحد الأدنى. إذا كانت أكبر من القيمة الأقصى ، فسيتم استبدالها بحد أقصى ، إلخ)

هل كانت مفيدة؟

المحلول

يمكنك كتابة طريقة تمديد:

public static T Clamp<T>(this T val, T min, T max) where T : IComparable<T>
{
    if (val.CompareTo(min) < 0) return min;
    else if(val.CompareTo(max) > 0) return max;
    else return val;
}

تحرير: تسير طرق التمديد في فصول ثابتة - نظرًا لأن هذه وظيفة منخفضة المستوى ، فمن المحتمل أن تذهب في مساحة الاسم الأساسية في مشروعك. يمكنك بعد ذلك استخدام الطريقة في أي ملف رمز يحتوي على توجيه لمساحة الاسم على سبيل المثال

using Core.ExtensionMethods

int i = 4.Clamp(1, 3);

.NET CORE 2.0

بدءًا من .NET Core 2.0 System.Math الآن لديه Clamp الطريقة التي يمكن استخدامها بدلاً من ذلك:

using System;

int i = Math.Clamp(4, 1, 3);

نصائح أخرى

محاولة:

public static int Clamp(int value, int min, int max)  
{  
    return (value < min) ? min : (value > max) ? max : value;  
}

فقط استخدم Math.Min و Math.Max:

x = Math.Min(Math.Max(x, a), b);

لا يوجد واحد ، لكن ليس من الصعب جدًا صنع واحدة. لقد وجدت واحدة هنا: المشبك

إنها:

public static T Clamp<T>(T value, T max, T min)
    where T : System.IComparable<T> {
        T result = value;
        if (value.CompareTo(max) > 0)
            result = max;
        if (value.CompareTo(min) < 0)
            result = min;
        return result;
    }

ويمكن استخدامه مثل:

int i = Clamp(12, 10, 0); -> i == 10
double d = Clamp(4.5, 10.0, 0.0); -> d == 4.5

لا يوجد واحد في مساحة الاسم

http://msdn.microsoft.com/en-us/library/system.math_members.aspx

هناك فصل MathHelper حيث يتوفر لاستوديو XNA Game إذا كان هذا هو ما تفعله:

http://msdn.microsoft.com/en-us/library/bb197892(v=xnagamestudio.31).aspx

فقط شارك حل لي مع وجود قضايا ومخاوف التعليقات ، حيثما أمكن ذلك:

public static T Clamped<T>(this T value, T min, T max) where T : IComparable<T> {
    if (value == null) throw new ArgumentNullException(nameof(value), "is null.");
    if (min == null) throw new ArgumentNullException(nameof(min), "is null.");
    if (max == null) throw new ArgumentNullException(nameof(max), "is null.");
    //If min <= max, clamp
    if (min.CompareTo(max) <= 0) return value.CompareTo(min) < 0 ? min : value.CompareTo(max) > 0 ? max : value;
    //If min > max, clamp on swapped min and max
    return value.CompareTo(max) < 0 ? max : value.CompareTo(min) > 0 ? min : value;
}

اختلافات:

  • يستخدم اسم الطريقة المضارع الفعل المناسب (ed) إلى (علاوة) تشير إلى أن القيمة لا يتم تثبيتها في مكانها ، وبدلاً من ذلك ، يتم إرجاع قيمة جديدة (انظر @تعليق Jimbalter).
  • هل مناسب null check على جميع المدخلات (انظر @تعليق jeppestignielsen).
  • مقايضات min و max إذا min > max (نرى @تعليق jeppestignielsen).

القيود: لا توجد مشابك واحدة. إذا max هو NaN, ، يعود دائما NaN (نرى تعليق هيرمان).

باستخدام الإجابات السابقة ، قمت بتكثيفها إلى الكود أدناه لاحتياجاتي. سيسمح لك هذا أيضًا بمشاركة الرقم فقط بواسطة Min أو Max.

public static class IComparableExtensions
{
    public static T Clamped<T>(this T value, T min, T max) 
        where T : IComparable<T>
    {
        return value.CompareTo(min) < 0 ? min : value.ClampedMaximum(max);
    }

    public static T ClampedMinimum<T>(this T value, T min)
        where T : IComparable<T>
    {
        return value.CompareTo(min) < 0 ? min : value;
    }

    public static T ClampedMaximum<T>(this T value, T max)
        where T : IComparable<T>
    {
        return value.CompareTo(max) > 0 ? max : value;
    }
}

يدعم الرمز أدناه تحديد الحدود بأي ترتيب (أي bound1 <= bound2, ، أو bound2 <= bound1). لقد وجدت هذا مفيدًا لقيم التثبيت المحسوبة من المعادلات الخطية (y=mx+b) حيث يمكن أن يزداد ميل الخط أو يتناقص.

أعرف: الكود يتكون من خمسة عوامل تعبير مشروطة. الشيء هو، إنها تعمل, والاختبارات أدناه تثبت ذلك. لا تتردد في إضافة أقواس غير ضرورية تمامًا إذا كنت ترغب في ذلك.

يمكنك بسهولة إنشاء أحمال زائدة أخرى لأنواع رقمية أخرى ونسخ/لصق الاختبارات بشكل أساسي.

تحذير: مقارنة أرقام النقاط العائمة ليست بسيطة. هذا الرمز لا ينفذ double مقارنات بقوة. استخدم مكتبة مقارنة نقطة عائمة لاستبدال استخدامات مشغلات المقارنة.

public static class MathExtensions
{
    public static double Clamp(this double value, double bound1, double bound2)
    {
        return bound1 <= bound2 ? value <= bound1 ? bound1 : value >= bound2 ? bound2 : value : value <= bound2 ? bound2 : value >= bound1 ? bound1 : value;
    }
}

اختبارات Xunit/FluentAssertions:

public class MathExtensionsTests
{
    [Theory]
    [InlineData(0, 0, 0, 0)]
    [InlineData(0, 0, 2, 0)]
    [InlineData(-1, 0, 2, 0)]
    [InlineData(1, 0, 2, 1)]
    [InlineData(2, 0, 2, 2)]
    [InlineData(3, 0, 2, 2)]
    [InlineData(0, 2, 0, 0)]
    [InlineData(-1, 2, 0, 0)]
    [InlineData(1, 2, 0, 1)]
    [InlineData(2, 2, 0, 2)]
    [InlineData(3, 2, 0, 2)]
    public void MustClamp(double value, double bound1, double bound2, double expectedValue)
    {
        value.Clamp(bound1, bound2).Should().Be(expectedValue);
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top