VB.NETにて出力する文章に雛形を用意し、その雛形の # に番号を当てはめようとしました。

<script runat="server" language="vb">
    function checkcode(s as String) as String
        System.Text.Encoding.UTF8.GetBytes(s) ' => 50
        System.Text.Encoding.UTF8.GetBytes("#") ' => 35
        Dim result as String = "(" + s + ") ###"
        result = result.replace("#","XX")
        return result
    end function

function checkcode2(s as String) as String
    Dim result as String = "(" + s + ")"
    return result
end function
</script>
<%
    body = "XXXXXXXXX Page #/#/# XXXXXXXXX"
    Dim reg As New Regex("(#)")

    REM Pattern 1
    body = reg.replace(body,checkcode("$1")) 

    REM Pattern 2
    body = body.Replace("#","!") 
%>

のようなコードを書き、(Pattern 1のとき)

XXXXXXXXX Page (XX) XXXXXX/(XX) XXXXXX/(XX) XXXXXX XXXXXXXXX

という結果を期待しました。しかし、これで得られる結果は

XXXXXXXXX Page (#) XXXXXX/(#) XXXXXX/(#) XXXXXX XXXXXXXXX

でした。そこで、checkcode2 に投げてみると、 (#) が帰ってきます。
が、この時 s に入っている # を GetBytes で取得し、 # 部分の文字コードを見てみると 50 になっているのです。&#50;は 2 なので、期待値でもありません。

そこで、(Pattern 2)で置換してみると、こちらは問題なく置換ができました。
この時の文字コードは 35 で、HTML上で &#35; と打てば # が出てきますので想定どおりです。

何故 Regex.Replace を通すと、 # が 35から50に変わってしまうのでしょうか。
お昼から悩み続けて解決できず・・・よろしくお願いします。

---------------------------------19:00 追記

例えば、 s を強制的に # の文字列に置き換えてみました。

<!doctype html>
<html>
<head>
<script runat="server" language="vb">
    function checkcode(s as String) as String
        Dim result as String = "(" + s + ") ###"
        result = result.replace("#","XX")
        return result
    end function


    function forcesharp(s as String) as String
        Dim result as String = "(#) ###"
        result = result.replace("#","XX")
        return result
    end function
</script>
</head>
<body>

<%
    Dim body as String = "XXXXXXXXX Page #/#/# XXXXXXXXX"
    Dim reg As New Regex("(#)")
%>
    <%= reg.replace(body,checkcode("$1")) %>
<hr />
    <%= reg.replace(body,forcesharp("$1")) %>

</body>
</html>


結果
XXXXXXXXX Page (#) XXXXXX/(#) XXXXXX/(#) XXXXXX XXXXXXXXX
------------------水平線--------------------
XXXXXXXXX Page (XX) XXXXXX/(XX) XXXXXX/(XX) XXXXXX XXXXXXXXX

forcesharp も checkcode も s には # が入っているはずですが、 s をそのまま使っているcheckcodeは # なのに置換されていません。
一方 forcesharp は s を使わず # の文字を改めて手入力していることも有り、正しく置換されています。
バイトコードに置き換えると、手入力したシャープは 35、パターンマッチで取り出したシャープは 50 となっていますが、そもそも手入力した # を検出しているはずなので # は 35のはず。
--------------------------------問題点が判明しました。
Perl頭で合ったことが原因のようでした。
Perlでは $body=~s/(#)/checkcode($1)/egsi; のように、$1 には # が入ってくるので、思い込みからこのトラブルが発生していました。
reg.replace(body,checkcode("$1"))は #ではなく $1が送られている、が原因でした。
--------------------------------解決策
現在以下のページを参考に、想定していた動作のする手段で続行しています。
https://msdn.microsoft.com/ja-jp/library/system.text.regularexpressions.matchevaluator(v=vs.110).aspx