How do I use if/else in a generic function? C#












-2















First I'd like to say that im pretty new in regards to coding, so don't kill me if the code looks horrible.



Alright, so the problem is that im trying to make a generic function which purpose is to take two sorted arrays and merge them into a new sorted array.
The problem im facing is trying to use if's in the function, and it doesn't let me use the < operand.



public object mergeTwoSorted<Tone, Ttwo>(Tone array, Ttwo array2)
{
object mergedArray = new object[array.Length + array2.Length];
for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i] > array2[i])

}
}
}


Any idea on how to tackle this problem?










share|improve this question




















  • 2





    This is a common problem, ValueType does not imply it is numeric, nor that you can compare with >. This seems like a problem you can solve another way. Maybe add what you're actually trying to achieve (rather than how you're trying to achieve it) and you'll get some better guidance. Another point is how would this behave if, for eaxmple Tone is an array of ints and Ttwo is an array of Monkeys

    – Jamiec
    Nov 21 '18 at 15:31








  • 4





    You want to compare two different types

    – miechooy
    Nov 21 '18 at 15:31






  • 3





    And also, you're checking array is ValueType, which is always false, regardless of the type of elements contained in the array. The array itself is always a reference type.

    – Rotem
    Nov 21 '18 at 15:32








  • 3





    You're missing the point of my question. Are there two different types here or not? Are you merging a sorted array of giraffes with a sorted array of apples, is the question.

    – Eric Lippert
    Nov 21 '18 at 15:56






  • 2





    If the two arrays are always of the same type then do not make two type parameters and do not use object. If the two input arrays are both the same type, just call that type T, and then the output array is also T.

    – Eric Lippert
    Nov 21 '18 at 15:58
















-2















First I'd like to say that im pretty new in regards to coding, so don't kill me if the code looks horrible.



Alright, so the problem is that im trying to make a generic function which purpose is to take two sorted arrays and merge them into a new sorted array.
The problem im facing is trying to use if's in the function, and it doesn't let me use the < operand.



public object mergeTwoSorted<Tone, Ttwo>(Tone array, Ttwo array2)
{
object mergedArray = new object[array.Length + array2.Length];
for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i] > array2[i])

}
}
}


Any idea on how to tackle this problem?










share|improve this question




















  • 2





    This is a common problem, ValueType does not imply it is numeric, nor that you can compare with >. This seems like a problem you can solve another way. Maybe add what you're actually trying to achieve (rather than how you're trying to achieve it) and you'll get some better guidance. Another point is how would this behave if, for eaxmple Tone is an array of ints and Ttwo is an array of Monkeys

    – Jamiec
    Nov 21 '18 at 15:31








  • 4





    You want to compare two different types

    – miechooy
    Nov 21 '18 at 15:31






  • 3





    And also, you're checking array is ValueType, which is always false, regardless of the type of elements contained in the array. The array itself is always a reference type.

    – Rotem
    Nov 21 '18 at 15:32








  • 3





    You're missing the point of my question. Are there two different types here or not? Are you merging a sorted array of giraffes with a sorted array of apples, is the question.

    – Eric Lippert
    Nov 21 '18 at 15:56






  • 2





    If the two arrays are always of the same type then do not make two type parameters and do not use object. If the two input arrays are both the same type, just call that type T, and then the output array is also T.

    – Eric Lippert
    Nov 21 '18 at 15:58














-2












-2








-2


0






First I'd like to say that im pretty new in regards to coding, so don't kill me if the code looks horrible.



Alright, so the problem is that im trying to make a generic function which purpose is to take two sorted arrays and merge them into a new sorted array.
The problem im facing is trying to use if's in the function, and it doesn't let me use the < operand.



public object mergeTwoSorted<Tone, Ttwo>(Tone array, Ttwo array2)
{
object mergedArray = new object[array.Length + array2.Length];
for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i] > array2[i])

}
}
}


Any idea on how to tackle this problem?










share|improve this question
















First I'd like to say that im pretty new in regards to coding, so don't kill me if the code looks horrible.



Alright, so the problem is that im trying to make a generic function which purpose is to take two sorted arrays and merge them into a new sorted array.
The problem im facing is trying to use if's in the function, and it doesn't let me use the < operand.



public object mergeTwoSorted<Tone, Ttwo>(Tone array, Ttwo array2)
{
object mergedArray = new object[array.Length + array2.Length];
for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i] > array2[i])

}
}
}


Any idea on how to tackle this problem?







c#






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 21 '18 at 16:10









Kevin Kouketsu

367214




367214










asked Nov 21 '18 at 15:29









Gil ShvarzmanGil Shvarzman

22




22








  • 2





    This is a common problem, ValueType does not imply it is numeric, nor that you can compare with >. This seems like a problem you can solve another way. Maybe add what you're actually trying to achieve (rather than how you're trying to achieve it) and you'll get some better guidance. Another point is how would this behave if, for eaxmple Tone is an array of ints and Ttwo is an array of Monkeys

    – Jamiec
    Nov 21 '18 at 15:31








  • 4





    You want to compare two different types

    – miechooy
    Nov 21 '18 at 15:31






  • 3





    And also, you're checking array is ValueType, which is always false, regardless of the type of elements contained in the array. The array itself is always a reference type.

    – Rotem
    Nov 21 '18 at 15:32








  • 3





    You're missing the point of my question. Are there two different types here or not? Are you merging a sorted array of giraffes with a sorted array of apples, is the question.

    – Eric Lippert
    Nov 21 '18 at 15:56






  • 2





    If the two arrays are always of the same type then do not make two type parameters and do not use object. If the two input arrays are both the same type, just call that type T, and then the output array is also T.

    – Eric Lippert
    Nov 21 '18 at 15:58














  • 2





    This is a common problem, ValueType does not imply it is numeric, nor that you can compare with >. This seems like a problem you can solve another way. Maybe add what you're actually trying to achieve (rather than how you're trying to achieve it) and you'll get some better guidance. Another point is how would this behave if, for eaxmple Tone is an array of ints and Ttwo is an array of Monkeys

    – Jamiec
    Nov 21 '18 at 15:31








  • 4





    You want to compare two different types

    – miechooy
    Nov 21 '18 at 15:31






  • 3





    And also, you're checking array is ValueType, which is always false, regardless of the type of elements contained in the array. The array itself is always a reference type.

    – Rotem
    Nov 21 '18 at 15:32








  • 3





    You're missing the point of my question. Are there two different types here or not? Are you merging a sorted array of giraffes with a sorted array of apples, is the question.

    – Eric Lippert
    Nov 21 '18 at 15:56






  • 2





    If the two arrays are always of the same type then do not make two type parameters and do not use object. If the two input arrays are both the same type, just call that type T, and then the output array is also T.

    – Eric Lippert
    Nov 21 '18 at 15:58








2




2





This is a common problem, ValueType does not imply it is numeric, nor that you can compare with >. This seems like a problem you can solve another way. Maybe add what you're actually trying to achieve (rather than how you're trying to achieve it) and you'll get some better guidance. Another point is how would this behave if, for eaxmple Tone is an array of ints and Ttwo is an array of Monkeys

– Jamiec
Nov 21 '18 at 15:31







This is a common problem, ValueType does not imply it is numeric, nor that you can compare with >. This seems like a problem you can solve another way. Maybe add what you're actually trying to achieve (rather than how you're trying to achieve it) and you'll get some better guidance. Another point is how would this behave if, for eaxmple Tone is an array of ints and Ttwo is an array of Monkeys

– Jamiec
Nov 21 '18 at 15:31






4




4





You want to compare two different types

– miechooy
Nov 21 '18 at 15:31





You want to compare two different types

– miechooy
Nov 21 '18 at 15:31




3




3





And also, you're checking array is ValueType, which is always false, regardless of the type of elements contained in the array. The array itself is always a reference type.

– Rotem
Nov 21 '18 at 15:32







And also, you're checking array is ValueType, which is always false, regardless of the type of elements contained in the array. The array itself is always a reference type.

– Rotem
Nov 21 '18 at 15:32






3




3





You're missing the point of my question. Are there two different types here or not? Are you merging a sorted array of giraffes with a sorted array of apples, is the question.

– Eric Lippert
Nov 21 '18 at 15:56





You're missing the point of my question. Are there two different types here or not? Are you merging a sorted array of giraffes with a sorted array of apples, is the question.

– Eric Lippert
Nov 21 '18 at 15:56




2




2





If the two arrays are always of the same type then do not make two type parameters and do not use object. If the two input arrays are both the same type, just call that type T, and then the output array is also T.

– Eric Lippert
Nov 21 '18 at 15:58





If the two arrays are always of the same type then do not make two type parameters and do not use object. If the two input arrays are both the same type, just call that type T, and then the output array is also T.

– Eric Lippert
Nov 21 '18 at 15:58












3 Answers
3






active

oldest

votes


















6















First I'd like to say that im pretty new in regards to coding, so don't kill me if the code looks horrible.




It looks pretty reasonable so far. It looks like what you're trying to do is to take two sorted arrays of two different types, but there is an ordering relationship between the two types. You're then merging the two arrays into an array of objects, such that the objects from the two arrays are still in the same order, but they are interleaved with each other to match the inter-type ordering relation, yes?



That is an unusual thing to do, but it is possible.



If that is not what you are doing, then you need to stop and re-design the code. In particular, if your intention is to take two arrays of the same type, then you must have one type parameter, not two, and you must make an array of T as the output, not object.



The problem is that there is in general no way to express "I have an ordering relationship between these two types" in C#. You'll have to provide a function that does that. Traditionally we provide a function that takes the two types and returns an integer: -1 if the first is the smaller, 1 if the second is the smaller, and 0 if they are equal.



If we have that then your method becomes:



public static object MergeTwoSorted<TOne, TTwo> (
TOne items1,
TTwo items2,
Func<TOne, TTwo, int> comparer)
{


Note that we are using standard C# conventions here. Methods begin with a capital, type parameters are TSomething, and so on. A Func<A, B, C> is a function that takes an A, a B, and returns a C. Methods that do not manipulate an instance of their class are static.



Note that there is no need to re-state in the name of a thing what its type is. Say what the thing is logically, not how it is stored:



    object merged = new object[items1.Length + items2.Length];


Now your loop needs some work:



    for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i] > array2[i])


Arrays are never value types. I think you do not understand the difference between values and references, and that is really important to understand, so do some research on that.



Also, you have a counter i which counts the big merged array, but you use that as an index into the small arrays. That is very wrong; do you see why?



Think about it this way: you are going to count through both arrays at the same time filling in the merged array. So that would be:



int current1 = 0;
int current2 = 0;
while (current1 + current2 < merged.Length)
{
if (comparer(items1[current1], items2[current2]) < 0)
{
// items1[current1] is the smaller
merged[current1+current2] = items1[current1];
current1 += 1;
}
else
{


There is a bug in the code above; can you find it? Hint: indices for all array accesses must be >= 0 and < Length of the array. Is there a way in the code I've written so far that this gets violated?




  • Can you fix the bug and finish it off?

  • Can you now make a call site that takes an array of strings, an array of numbers, and an ordering relationship between strings and numbers, and merges the arrays?






share|improve this answer


























  • First of all, thank you for the comperhensive reply. I don't understand why you mean by "inter-type ordering relation". Let's say I have a list of chars {a,b,c} and ints {1,2,3}. I fail to see a relationship between them, unless we say a is the first letter of the alphabet, so it is comparable to 1, which is the start of all positive numbers.

    – Gil Shvarzman
    Nov 21 '18 at 16:14








  • 1





    @GilShvarzman: You keep on not answering the important question I'm asking you. Why are there two type parameters TOne and TTwo? This mean that there are two arrays of two different types that you are trying to merge, and they can be any types. You have a sorted array of newspapers and a sorted array of turtles, and you wish to merge them together. That means that there must be a way to tell whether a given newspaper is smaller than a given turtle. You must have an inter-type ordering relation. Again if that is not your scenario then do not make two type parameters.

    – Eric Lippert
    Nov 21 '18 at 16:17






  • 1





    @GilShvarzman: If you want to merge two arrays of the same type then the signature must be public static T Merge<T>(T items1, T item2), and you can then make a constraint of IComparable<T> on T to indicate that a T may be ordered with respect to another T.

    – Eric Lippert
    Nov 21 '18 at 16:19











  • @GilShvarzman: I strongly suspect that you are attempting to run before you walk here. Designing generic algorithms is what you should do after you have mastered designing non-generic algorithms. If you cannot write the code perfectly for ints, and doubles, and strings, all individually, then you will not be successful writing a generic implementation.

    – Eric Lippert
    Nov 21 '18 at 16:20











  • The reason I wrote 2 parameters Tone and Ttwo is because the function is supposed to merge them. They can be of any type indeed. I understand now what you mean by relationship, although I don't think I am able to implement it. A little above my current level perhaps. :

    – Gil Shvarzman
    Nov 21 '18 at 16:22



















-3














public static object mergeTwoSorted<Tone, Ttwo>(Tone array, Ttwo array2)  
where Tone : IComparable<Ttwo>
{
var mergedArray = new object[array.Length + array2.Length];
for (int i = 0; i < mergedArray.Length; i++)
{
if (array is ValueType && array2 is ValueType)
{
if (array[i].CompareTo( array2[i] )>0)

}
}
return mergedArray;
}





share|improve this answer































    -7














    If you want to use specific operations on Generics, you have to limit them with a where clause accordingly. As when working with Fractural Numebrs, you need a common denominator.



    Something like a "IMergable" interface that you have to write yourself.



    public IMergeable mergeTwoSorted<Tone, Ttwo> (Tone array, Ttwo array2)
    where Tone : IMergeable, Ttwo : IMergeable
    {
    IMergeable mergedArray = new IMergeable[array.Length + array2.Length];
    for (int i = 0; i < mergedArray.Length; i++)
    {
    if (array is ValueType && array2 is ValueType)
    {
    if (array[i] > array2[i])

    }
    }
    }


    Alternatively, you could jsut use one type:



    public Tone mergeTwoSorted<Tone> (Tone array, Tone array2)
    {
    IMergeable mergedArray = new IMergeable[array.Length + array2.Length];
    for (int i = 0; i < mergedArray.Length; i++)
    {
    if (array is ValueType && array2 is ValueType)
    {
    if (array[i] > array2[i])

    }
    }
    }





    share|improve this answer
























    • 1) You mention an IMergeable interface but don't define it and don't use it in the code, instead using > 2) You check array is ValueType which is always false.

      – Rotem
      Nov 21 '18 at 15:59






    • 2





      I hope this doesn't come off as offensive, it's meant to be constructive, but perhaps others believe that if you haven't taken the time to try to run your method and see if it works before posting it then they shouldn't take the time to give you specific feedback.

      – Rotem
      Nov 21 '18 at 16:04













    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53415383%2fhow-do-i-use-if-else-in-a-generic-function-c-sharp%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    3 Answers
    3






    active

    oldest

    votes








    3 Answers
    3






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    6















    First I'd like to say that im pretty new in regards to coding, so don't kill me if the code looks horrible.




    It looks pretty reasonable so far. It looks like what you're trying to do is to take two sorted arrays of two different types, but there is an ordering relationship between the two types. You're then merging the two arrays into an array of objects, such that the objects from the two arrays are still in the same order, but they are interleaved with each other to match the inter-type ordering relation, yes?



    That is an unusual thing to do, but it is possible.



    If that is not what you are doing, then you need to stop and re-design the code. In particular, if your intention is to take two arrays of the same type, then you must have one type parameter, not two, and you must make an array of T as the output, not object.



    The problem is that there is in general no way to express "I have an ordering relationship between these two types" in C#. You'll have to provide a function that does that. Traditionally we provide a function that takes the two types and returns an integer: -1 if the first is the smaller, 1 if the second is the smaller, and 0 if they are equal.



    If we have that then your method becomes:



    public static object MergeTwoSorted<TOne, TTwo> (
    TOne items1,
    TTwo items2,
    Func<TOne, TTwo, int> comparer)
    {


    Note that we are using standard C# conventions here. Methods begin with a capital, type parameters are TSomething, and so on. A Func<A, B, C> is a function that takes an A, a B, and returns a C. Methods that do not manipulate an instance of their class are static.



    Note that there is no need to re-state in the name of a thing what its type is. Say what the thing is logically, not how it is stored:



        object merged = new object[items1.Length + items2.Length];


    Now your loop needs some work:



        for (int i = 0; i < mergedArray.Length; i++)
    {
    if (array is ValueType && array2 is ValueType)
    {
    if (array[i] > array2[i])


    Arrays are never value types. I think you do not understand the difference between values and references, and that is really important to understand, so do some research on that.



    Also, you have a counter i which counts the big merged array, but you use that as an index into the small arrays. That is very wrong; do you see why?



    Think about it this way: you are going to count through both arrays at the same time filling in the merged array. So that would be:



    int current1 = 0;
    int current2 = 0;
    while (current1 + current2 < merged.Length)
    {
    if (comparer(items1[current1], items2[current2]) < 0)
    {
    // items1[current1] is the smaller
    merged[current1+current2] = items1[current1];
    current1 += 1;
    }
    else
    {


    There is a bug in the code above; can you find it? Hint: indices for all array accesses must be >= 0 and < Length of the array. Is there a way in the code I've written so far that this gets violated?




    • Can you fix the bug and finish it off?

    • Can you now make a call site that takes an array of strings, an array of numbers, and an ordering relationship between strings and numbers, and merges the arrays?






    share|improve this answer


























    • First of all, thank you for the comperhensive reply. I don't understand why you mean by "inter-type ordering relation". Let's say I have a list of chars {a,b,c} and ints {1,2,3}. I fail to see a relationship between them, unless we say a is the first letter of the alphabet, so it is comparable to 1, which is the start of all positive numbers.

      – Gil Shvarzman
      Nov 21 '18 at 16:14








    • 1





      @GilShvarzman: You keep on not answering the important question I'm asking you. Why are there two type parameters TOne and TTwo? This mean that there are two arrays of two different types that you are trying to merge, and they can be any types. You have a sorted array of newspapers and a sorted array of turtles, and you wish to merge them together. That means that there must be a way to tell whether a given newspaper is smaller than a given turtle. You must have an inter-type ordering relation. Again if that is not your scenario then do not make two type parameters.

      – Eric Lippert
      Nov 21 '18 at 16:17






    • 1





      @GilShvarzman: If you want to merge two arrays of the same type then the signature must be public static T Merge<T>(T items1, T item2), and you can then make a constraint of IComparable<T> on T to indicate that a T may be ordered with respect to another T.

      – Eric Lippert
      Nov 21 '18 at 16:19











    • @GilShvarzman: I strongly suspect that you are attempting to run before you walk here. Designing generic algorithms is what you should do after you have mastered designing non-generic algorithms. If you cannot write the code perfectly for ints, and doubles, and strings, all individually, then you will not be successful writing a generic implementation.

      – Eric Lippert
      Nov 21 '18 at 16:20











    • The reason I wrote 2 parameters Tone and Ttwo is because the function is supposed to merge them. They can be of any type indeed. I understand now what you mean by relationship, although I don't think I am able to implement it. A little above my current level perhaps. :

      – Gil Shvarzman
      Nov 21 '18 at 16:22
















    6















    First I'd like to say that im pretty new in regards to coding, so don't kill me if the code looks horrible.




    It looks pretty reasonable so far. It looks like what you're trying to do is to take two sorted arrays of two different types, but there is an ordering relationship between the two types. You're then merging the two arrays into an array of objects, such that the objects from the two arrays are still in the same order, but they are interleaved with each other to match the inter-type ordering relation, yes?



    That is an unusual thing to do, but it is possible.



    If that is not what you are doing, then you need to stop and re-design the code. In particular, if your intention is to take two arrays of the same type, then you must have one type parameter, not two, and you must make an array of T as the output, not object.



    The problem is that there is in general no way to express "I have an ordering relationship between these two types" in C#. You'll have to provide a function that does that. Traditionally we provide a function that takes the two types and returns an integer: -1 if the first is the smaller, 1 if the second is the smaller, and 0 if they are equal.



    If we have that then your method becomes:



    public static object MergeTwoSorted<TOne, TTwo> (
    TOne items1,
    TTwo items2,
    Func<TOne, TTwo, int> comparer)
    {


    Note that we are using standard C# conventions here. Methods begin with a capital, type parameters are TSomething, and so on. A Func<A, B, C> is a function that takes an A, a B, and returns a C. Methods that do not manipulate an instance of their class are static.



    Note that there is no need to re-state in the name of a thing what its type is. Say what the thing is logically, not how it is stored:



        object merged = new object[items1.Length + items2.Length];


    Now your loop needs some work:



        for (int i = 0; i < mergedArray.Length; i++)
    {
    if (array is ValueType && array2 is ValueType)
    {
    if (array[i] > array2[i])


    Arrays are never value types. I think you do not understand the difference between values and references, and that is really important to understand, so do some research on that.



    Also, you have a counter i which counts the big merged array, but you use that as an index into the small arrays. That is very wrong; do you see why?



    Think about it this way: you are going to count through both arrays at the same time filling in the merged array. So that would be:



    int current1 = 0;
    int current2 = 0;
    while (current1 + current2 < merged.Length)
    {
    if (comparer(items1[current1], items2[current2]) < 0)
    {
    // items1[current1] is the smaller
    merged[current1+current2] = items1[current1];
    current1 += 1;
    }
    else
    {


    There is a bug in the code above; can you find it? Hint: indices for all array accesses must be >= 0 and < Length of the array. Is there a way in the code I've written so far that this gets violated?




    • Can you fix the bug and finish it off?

    • Can you now make a call site that takes an array of strings, an array of numbers, and an ordering relationship between strings and numbers, and merges the arrays?






    share|improve this answer


























    • First of all, thank you for the comperhensive reply. I don't understand why you mean by "inter-type ordering relation". Let's say I have a list of chars {a,b,c} and ints {1,2,3}. I fail to see a relationship between them, unless we say a is the first letter of the alphabet, so it is comparable to 1, which is the start of all positive numbers.

      – Gil Shvarzman
      Nov 21 '18 at 16:14








    • 1





      @GilShvarzman: You keep on not answering the important question I'm asking you. Why are there two type parameters TOne and TTwo? This mean that there are two arrays of two different types that you are trying to merge, and they can be any types. You have a sorted array of newspapers and a sorted array of turtles, and you wish to merge them together. That means that there must be a way to tell whether a given newspaper is smaller than a given turtle. You must have an inter-type ordering relation. Again if that is not your scenario then do not make two type parameters.

      – Eric Lippert
      Nov 21 '18 at 16:17






    • 1





      @GilShvarzman: If you want to merge two arrays of the same type then the signature must be public static T Merge<T>(T items1, T item2), and you can then make a constraint of IComparable<T> on T to indicate that a T may be ordered with respect to another T.

      – Eric Lippert
      Nov 21 '18 at 16:19











    • @GilShvarzman: I strongly suspect that you are attempting to run before you walk here. Designing generic algorithms is what you should do after you have mastered designing non-generic algorithms. If you cannot write the code perfectly for ints, and doubles, and strings, all individually, then you will not be successful writing a generic implementation.

      – Eric Lippert
      Nov 21 '18 at 16:20











    • The reason I wrote 2 parameters Tone and Ttwo is because the function is supposed to merge them. They can be of any type indeed. I understand now what you mean by relationship, although I don't think I am able to implement it. A little above my current level perhaps. :

      – Gil Shvarzman
      Nov 21 '18 at 16:22














    6












    6








    6








    First I'd like to say that im pretty new in regards to coding, so don't kill me if the code looks horrible.




    It looks pretty reasonable so far. It looks like what you're trying to do is to take two sorted arrays of two different types, but there is an ordering relationship between the two types. You're then merging the two arrays into an array of objects, such that the objects from the two arrays are still in the same order, but they are interleaved with each other to match the inter-type ordering relation, yes?



    That is an unusual thing to do, but it is possible.



    If that is not what you are doing, then you need to stop and re-design the code. In particular, if your intention is to take two arrays of the same type, then you must have one type parameter, not two, and you must make an array of T as the output, not object.



    The problem is that there is in general no way to express "I have an ordering relationship between these two types" in C#. You'll have to provide a function that does that. Traditionally we provide a function that takes the two types and returns an integer: -1 if the first is the smaller, 1 if the second is the smaller, and 0 if they are equal.



    If we have that then your method becomes:



    public static object MergeTwoSorted<TOne, TTwo> (
    TOne items1,
    TTwo items2,
    Func<TOne, TTwo, int> comparer)
    {


    Note that we are using standard C# conventions here. Methods begin with a capital, type parameters are TSomething, and so on. A Func<A, B, C> is a function that takes an A, a B, and returns a C. Methods that do not manipulate an instance of their class are static.



    Note that there is no need to re-state in the name of a thing what its type is. Say what the thing is logically, not how it is stored:



        object merged = new object[items1.Length + items2.Length];


    Now your loop needs some work:



        for (int i = 0; i < mergedArray.Length; i++)
    {
    if (array is ValueType && array2 is ValueType)
    {
    if (array[i] > array2[i])


    Arrays are never value types. I think you do not understand the difference between values and references, and that is really important to understand, so do some research on that.



    Also, you have a counter i which counts the big merged array, but you use that as an index into the small arrays. That is very wrong; do you see why?



    Think about it this way: you are going to count through both arrays at the same time filling in the merged array. So that would be:



    int current1 = 0;
    int current2 = 0;
    while (current1 + current2 < merged.Length)
    {
    if (comparer(items1[current1], items2[current2]) < 0)
    {
    // items1[current1] is the smaller
    merged[current1+current2] = items1[current1];
    current1 += 1;
    }
    else
    {


    There is a bug in the code above; can you find it? Hint: indices for all array accesses must be >= 0 and < Length of the array. Is there a way in the code I've written so far that this gets violated?




    • Can you fix the bug and finish it off?

    • Can you now make a call site that takes an array of strings, an array of numbers, and an ordering relationship between strings and numbers, and merges the arrays?






    share|improve this answer
















    First I'd like to say that im pretty new in regards to coding, so don't kill me if the code looks horrible.




    It looks pretty reasonable so far. It looks like what you're trying to do is to take two sorted arrays of two different types, but there is an ordering relationship between the two types. You're then merging the two arrays into an array of objects, such that the objects from the two arrays are still in the same order, but they are interleaved with each other to match the inter-type ordering relation, yes?



    That is an unusual thing to do, but it is possible.



    If that is not what you are doing, then you need to stop and re-design the code. In particular, if your intention is to take two arrays of the same type, then you must have one type parameter, not two, and you must make an array of T as the output, not object.



    The problem is that there is in general no way to express "I have an ordering relationship between these two types" in C#. You'll have to provide a function that does that. Traditionally we provide a function that takes the two types and returns an integer: -1 if the first is the smaller, 1 if the second is the smaller, and 0 if they are equal.



    If we have that then your method becomes:



    public static object MergeTwoSorted<TOne, TTwo> (
    TOne items1,
    TTwo items2,
    Func<TOne, TTwo, int> comparer)
    {


    Note that we are using standard C# conventions here. Methods begin with a capital, type parameters are TSomething, and so on. A Func<A, B, C> is a function that takes an A, a B, and returns a C. Methods that do not manipulate an instance of their class are static.



    Note that there is no need to re-state in the name of a thing what its type is. Say what the thing is logically, not how it is stored:



        object merged = new object[items1.Length + items2.Length];


    Now your loop needs some work:



        for (int i = 0; i < mergedArray.Length; i++)
    {
    if (array is ValueType && array2 is ValueType)
    {
    if (array[i] > array2[i])


    Arrays are never value types. I think you do not understand the difference between values and references, and that is really important to understand, so do some research on that.



    Also, you have a counter i which counts the big merged array, but you use that as an index into the small arrays. That is very wrong; do you see why?



    Think about it this way: you are going to count through both arrays at the same time filling in the merged array. So that would be:



    int current1 = 0;
    int current2 = 0;
    while (current1 + current2 < merged.Length)
    {
    if (comparer(items1[current1], items2[current2]) < 0)
    {
    // items1[current1] is the smaller
    merged[current1+current2] = items1[current1];
    current1 += 1;
    }
    else
    {


    There is a bug in the code above; can you find it? Hint: indices for all array accesses must be >= 0 and < Length of the array. Is there a way in the code I've written so far that this gets violated?




    • Can you fix the bug and finish it off?

    • Can you now make a call site that takes an array of strings, an array of numbers, and an ordering relationship between strings and numbers, and merges the arrays?







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 21 '18 at 16:05

























    answered Nov 21 '18 at 15:56









    Eric LippertEric Lippert

    545k14610671951




    545k14610671951













    • First of all, thank you for the comperhensive reply. I don't understand why you mean by "inter-type ordering relation". Let's say I have a list of chars {a,b,c} and ints {1,2,3}. I fail to see a relationship between them, unless we say a is the first letter of the alphabet, so it is comparable to 1, which is the start of all positive numbers.

      – Gil Shvarzman
      Nov 21 '18 at 16:14








    • 1





      @GilShvarzman: You keep on not answering the important question I'm asking you. Why are there two type parameters TOne and TTwo? This mean that there are two arrays of two different types that you are trying to merge, and they can be any types. You have a sorted array of newspapers and a sorted array of turtles, and you wish to merge them together. That means that there must be a way to tell whether a given newspaper is smaller than a given turtle. You must have an inter-type ordering relation. Again if that is not your scenario then do not make two type parameters.

      – Eric Lippert
      Nov 21 '18 at 16:17






    • 1





      @GilShvarzman: If you want to merge two arrays of the same type then the signature must be public static T Merge<T>(T items1, T item2), and you can then make a constraint of IComparable<T> on T to indicate that a T may be ordered with respect to another T.

      – Eric Lippert
      Nov 21 '18 at 16:19











    • @GilShvarzman: I strongly suspect that you are attempting to run before you walk here. Designing generic algorithms is what you should do after you have mastered designing non-generic algorithms. If you cannot write the code perfectly for ints, and doubles, and strings, all individually, then you will not be successful writing a generic implementation.

      – Eric Lippert
      Nov 21 '18 at 16:20











    • The reason I wrote 2 parameters Tone and Ttwo is because the function is supposed to merge them. They can be of any type indeed. I understand now what you mean by relationship, although I don't think I am able to implement it. A little above my current level perhaps. :

      – Gil Shvarzman
      Nov 21 '18 at 16:22



















    • First of all, thank you for the comperhensive reply. I don't understand why you mean by "inter-type ordering relation". Let's say I have a list of chars {a,b,c} and ints {1,2,3}. I fail to see a relationship between them, unless we say a is the first letter of the alphabet, so it is comparable to 1, which is the start of all positive numbers.

      – Gil Shvarzman
      Nov 21 '18 at 16:14








    • 1





      @GilShvarzman: You keep on not answering the important question I'm asking you. Why are there two type parameters TOne and TTwo? This mean that there are two arrays of two different types that you are trying to merge, and they can be any types. You have a sorted array of newspapers and a sorted array of turtles, and you wish to merge them together. That means that there must be a way to tell whether a given newspaper is smaller than a given turtle. You must have an inter-type ordering relation. Again if that is not your scenario then do not make two type parameters.

      – Eric Lippert
      Nov 21 '18 at 16:17






    • 1





      @GilShvarzman: If you want to merge two arrays of the same type then the signature must be public static T Merge<T>(T items1, T item2), and you can then make a constraint of IComparable<T> on T to indicate that a T may be ordered with respect to another T.

      – Eric Lippert
      Nov 21 '18 at 16:19











    • @GilShvarzman: I strongly suspect that you are attempting to run before you walk here. Designing generic algorithms is what you should do after you have mastered designing non-generic algorithms. If you cannot write the code perfectly for ints, and doubles, and strings, all individually, then you will not be successful writing a generic implementation.

      – Eric Lippert
      Nov 21 '18 at 16:20











    • The reason I wrote 2 parameters Tone and Ttwo is because the function is supposed to merge them. They can be of any type indeed. I understand now what you mean by relationship, although I don't think I am able to implement it. A little above my current level perhaps. :

      – Gil Shvarzman
      Nov 21 '18 at 16:22

















    First of all, thank you for the comperhensive reply. I don't understand why you mean by "inter-type ordering relation". Let's say I have a list of chars {a,b,c} and ints {1,2,3}. I fail to see a relationship between them, unless we say a is the first letter of the alphabet, so it is comparable to 1, which is the start of all positive numbers.

    – Gil Shvarzman
    Nov 21 '18 at 16:14







    First of all, thank you for the comperhensive reply. I don't understand why you mean by "inter-type ordering relation". Let's say I have a list of chars {a,b,c} and ints {1,2,3}. I fail to see a relationship between them, unless we say a is the first letter of the alphabet, so it is comparable to 1, which is the start of all positive numbers.

    – Gil Shvarzman
    Nov 21 '18 at 16:14






    1




    1





    @GilShvarzman: You keep on not answering the important question I'm asking you. Why are there two type parameters TOne and TTwo? This mean that there are two arrays of two different types that you are trying to merge, and they can be any types. You have a sorted array of newspapers and a sorted array of turtles, and you wish to merge them together. That means that there must be a way to tell whether a given newspaper is smaller than a given turtle. You must have an inter-type ordering relation. Again if that is not your scenario then do not make two type parameters.

    – Eric Lippert
    Nov 21 '18 at 16:17





    @GilShvarzman: You keep on not answering the important question I'm asking you. Why are there two type parameters TOne and TTwo? This mean that there are two arrays of two different types that you are trying to merge, and they can be any types. You have a sorted array of newspapers and a sorted array of turtles, and you wish to merge them together. That means that there must be a way to tell whether a given newspaper is smaller than a given turtle. You must have an inter-type ordering relation. Again if that is not your scenario then do not make two type parameters.

    – Eric Lippert
    Nov 21 '18 at 16:17




    1




    1





    @GilShvarzman: If you want to merge two arrays of the same type then the signature must be public static T Merge<T>(T items1, T item2), and you can then make a constraint of IComparable<T> on T to indicate that a T may be ordered with respect to another T.

    – Eric Lippert
    Nov 21 '18 at 16:19





    @GilShvarzman: If you want to merge two arrays of the same type then the signature must be public static T Merge<T>(T items1, T item2), and you can then make a constraint of IComparable<T> on T to indicate that a T may be ordered with respect to another T.

    – Eric Lippert
    Nov 21 '18 at 16:19













    @GilShvarzman: I strongly suspect that you are attempting to run before you walk here. Designing generic algorithms is what you should do after you have mastered designing non-generic algorithms. If you cannot write the code perfectly for ints, and doubles, and strings, all individually, then you will not be successful writing a generic implementation.

    – Eric Lippert
    Nov 21 '18 at 16:20





    @GilShvarzman: I strongly suspect that you are attempting to run before you walk here. Designing generic algorithms is what you should do after you have mastered designing non-generic algorithms. If you cannot write the code perfectly for ints, and doubles, and strings, all individually, then you will not be successful writing a generic implementation.

    – Eric Lippert
    Nov 21 '18 at 16:20













    The reason I wrote 2 parameters Tone and Ttwo is because the function is supposed to merge them. They can be of any type indeed. I understand now what you mean by relationship, although I don't think I am able to implement it. A little above my current level perhaps. :

    – Gil Shvarzman
    Nov 21 '18 at 16:22





    The reason I wrote 2 parameters Tone and Ttwo is because the function is supposed to merge them. They can be of any type indeed. I understand now what you mean by relationship, although I don't think I am able to implement it. A little above my current level perhaps. :

    – Gil Shvarzman
    Nov 21 '18 at 16:22













    -3














    public static object mergeTwoSorted<Tone, Ttwo>(Tone array, Ttwo array2)  
    where Tone : IComparable<Ttwo>
    {
    var mergedArray = new object[array.Length + array2.Length];
    for (int i = 0; i < mergedArray.Length; i++)
    {
    if (array is ValueType && array2 is ValueType)
    {
    if (array[i].CompareTo( array2[i] )>0)

    }
    }
    return mergedArray;
    }





    share|improve this answer




























      -3














      public static object mergeTwoSorted<Tone, Ttwo>(Tone array, Ttwo array2)  
      where Tone : IComparable<Ttwo>
      {
      var mergedArray = new object[array.Length + array2.Length];
      for (int i = 0; i < mergedArray.Length; i++)
      {
      if (array is ValueType && array2 is ValueType)
      {
      if (array[i].CompareTo( array2[i] )>0)

      }
      }
      return mergedArray;
      }





      share|improve this answer


























        -3












        -3








        -3







        public static object mergeTwoSorted<Tone, Ttwo>(Tone array, Ttwo array2)  
        where Tone : IComparable<Ttwo>
        {
        var mergedArray = new object[array.Length + array2.Length];
        for (int i = 0; i < mergedArray.Length; i++)
        {
        if (array is ValueType && array2 is ValueType)
        {
        if (array[i].CompareTo( array2[i] )>0)

        }
        }
        return mergedArray;
        }





        share|improve this answer













        public static object mergeTwoSorted<Tone, Ttwo>(Tone array, Ttwo array2)  
        where Tone : IComparable<Ttwo>
        {
        var mergedArray = new object[array.Length + array2.Length];
        for (int i = 0; i < mergedArray.Length; i++)
        {
        if (array is ValueType && array2 is ValueType)
        {
        if (array[i].CompareTo( array2[i] )>0)

        }
        }
        return mergedArray;
        }






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 21 '18 at 15:37









        themadmaxthemadmax

        1,3541624




        1,3541624























            -7














            If you want to use specific operations on Generics, you have to limit them with a where clause accordingly. As when working with Fractural Numebrs, you need a common denominator.



            Something like a "IMergable" interface that you have to write yourself.



            public IMergeable mergeTwoSorted<Tone, Ttwo> (Tone array, Ttwo array2)
            where Tone : IMergeable, Ttwo : IMergeable
            {
            IMergeable mergedArray = new IMergeable[array.Length + array2.Length];
            for (int i = 0; i < mergedArray.Length; i++)
            {
            if (array is ValueType && array2 is ValueType)
            {
            if (array[i] > array2[i])

            }
            }
            }


            Alternatively, you could jsut use one type:



            public Tone mergeTwoSorted<Tone> (Tone array, Tone array2)
            {
            IMergeable mergedArray = new IMergeable[array.Length + array2.Length];
            for (int i = 0; i < mergedArray.Length; i++)
            {
            if (array is ValueType && array2 is ValueType)
            {
            if (array[i] > array2[i])

            }
            }
            }





            share|improve this answer
























            • 1) You mention an IMergeable interface but don't define it and don't use it in the code, instead using > 2) You check array is ValueType which is always false.

              – Rotem
              Nov 21 '18 at 15:59






            • 2





              I hope this doesn't come off as offensive, it's meant to be constructive, but perhaps others believe that if you haven't taken the time to try to run your method and see if it works before posting it then they shouldn't take the time to give you specific feedback.

              – Rotem
              Nov 21 '18 at 16:04


















            -7














            If you want to use specific operations on Generics, you have to limit them with a where clause accordingly. As when working with Fractural Numebrs, you need a common denominator.



            Something like a "IMergable" interface that you have to write yourself.



            public IMergeable mergeTwoSorted<Tone, Ttwo> (Tone array, Ttwo array2)
            where Tone : IMergeable, Ttwo : IMergeable
            {
            IMergeable mergedArray = new IMergeable[array.Length + array2.Length];
            for (int i = 0; i < mergedArray.Length; i++)
            {
            if (array is ValueType && array2 is ValueType)
            {
            if (array[i] > array2[i])

            }
            }
            }


            Alternatively, you could jsut use one type:



            public Tone mergeTwoSorted<Tone> (Tone array, Tone array2)
            {
            IMergeable mergedArray = new IMergeable[array.Length + array2.Length];
            for (int i = 0; i < mergedArray.Length; i++)
            {
            if (array is ValueType && array2 is ValueType)
            {
            if (array[i] > array2[i])

            }
            }
            }





            share|improve this answer
























            • 1) You mention an IMergeable interface but don't define it and don't use it in the code, instead using > 2) You check array is ValueType which is always false.

              – Rotem
              Nov 21 '18 at 15:59






            • 2





              I hope this doesn't come off as offensive, it's meant to be constructive, but perhaps others believe that if you haven't taken the time to try to run your method and see if it works before posting it then they shouldn't take the time to give you specific feedback.

              – Rotem
              Nov 21 '18 at 16:04
















            -7












            -7








            -7







            If you want to use specific operations on Generics, you have to limit them with a where clause accordingly. As when working with Fractural Numebrs, you need a common denominator.



            Something like a "IMergable" interface that you have to write yourself.



            public IMergeable mergeTwoSorted<Tone, Ttwo> (Tone array, Ttwo array2)
            where Tone : IMergeable, Ttwo : IMergeable
            {
            IMergeable mergedArray = new IMergeable[array.Length + array2.Length];
            for (int i = 0; i < mergedArray.Length; i++)
            {
            if (array is ValueType && array2 is ValueType)
            {
            if (array[i] > array2[i])

            }
            }
            }


            Alternatively, you could jsut use one type:



            public Tone mergeTwoSorted<Tone> (Tone array, Tone array2)
            {
            IMergeable mergedArray = new IMergeable[array.Length + array2.Length];
            for (int i = 0; i < mergedArray.Length; i++)
            {
            if (array is ValueType && array2 is ValueType)
            {
            if (array[i] > array2[i])

            }
            }
            }





            share|improve this answer













            If you want to use specific operations on Generics, you have to limit them with a where clause accordingly. As when working with Fractural Numebrs, you need a common denominator.



            Something like a "IMergable" interface that you have to write yourself.



            public IMergeable mergeTwoSorted<Tone, Ttwo> (Tone array, Ttwo array2)
            where Tone : IMergeable, Ttwo : IMergeable
            {
            IMergeable mergedArray = new IMergeable[array.Length + array2.Length];
            for (int i = 0; i < mergedArray.Length; i++)
            {
            if (array is ValueType && array2 is ValueType)
            {
            if (array[i] > array2[i])

            }
            }
            }


            Alternatively, you could jsut use one type:



            public Tone mergeTwoSorted<Tone> (Tone array, Tone array2)
            {
            IMergeable mergedArray = new IMergeable[array.Length + array2.Length];
            for (int i = 0; i < mergedArray.Length; i++)
            {
            if (array is ValueType && array2 is ValueType)
            {
            if (array[i] > array2[i])

            }
            }
            }






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 21 '18 at 15:42









            ChristopherChristopher

            2,9962824




            2,9962824













            • 1) You mention an IMergeable interface but don't define it and don't use it in the code, instead using > 2) You check array is ValueType which is always false.

              – Rotem
              Nov 21 '18 at 15:59






            • 2





              I hope this doesn't come off as offensive, it's meant to be constructive, but perhaps others believe that if you haven't taken the time to try to run your method and see if it works before posting it then they shouldn't take the time to give you specific feedback.

              – Rotem
              Nov 21 '18 at 16:04





















            • 1) You mention an IMergeable interface but don't define it and don't use it in the code, instead using > 2) You check array is ValueType which is always false.

              – Rotem
              Nov 21 '18 at 15:59






            • 2





              I hope this doesn't come off as offensive, it's meant to be constructive, but perhaps others believe that if you haven't taken the time to try to run your method and see if it works before posting it then they shouldn't take the time to give you specific feedback.

              – Rotem
              Nov 21 '18 at 16:04



















            1) You mention an IMergeable interface but don't define it and don't use it in the code, instead using > 2) You check array is ValueType which is always false.

            – Rotem
            Nov 21 '18 at 15:59





            1) You mention an IMergeable interface but don't define it and don't use it in the code, instead using > 2) You check array is ValueType which is always false.

            – Rotem
            Nov 21 '18 at 15:59




            2




            2





            I hope this doesn't come off as offensive, it's meant to be constructive, but perhaps others believe that if you haven't taken the time to try to run your method and see if it works before posting it then they shouldn't take the time to give you specific feedback.

            – Rotem
            Nov 21 '18 at 16:04







            I hope this doesn't come off as offensive, it's meant to be constructive, but perhaps others believe that if you haven't taken the time to try to run your method and see if it works before posting it then they shouldn't take the time to give you specific feedback.

            – Rotem
            Nov 21 '18 at 16:04




















            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53415383%2fhow-do-i-use-if-else-in-a-generic-function-c-sharp%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Biblatex bibliography style without URLs when DOI exists (in Overleaf with Zotero bibliography)

            ComboBox Display Member on multiple fields

            Is it possible to collect Nectar points via Trainline?